Skip to content

Commit b9fe6d8

Browse files
committed
Avoid NPE in case of @lazy @Autowired(required=false)
Issue: SPR-13967
1 parent d8a0559 commit b9fe6d8

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

spring-context/src/main/java/org/springframework/context/annotation/ContextAnnotationAutowireCandidateResolver.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.aop.TargetSource;
2323
import org.springframework.aop.framework.ProxyFactory;
24+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2425
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
2526
import org.springframework.beans.factory.config.DependencyDescriptor;
2627
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -79,7 +80,12 @@ public boolean isStatic() {
7980
}
8081
@Override
8182
public Object getTarget() {
82-
return beanFactory.doResolveDependency(descriptor, beanName, null, null);
83+
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
84+
if (target == null) {
85+
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(),
86+
"Optional dependency not present for lazy injection point");
87+
}
88+
return target;
8389
}
8490
@Override
8591
public void releaseTarget(Object target) {

spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -118,6 +118,28 @@ public void testLazyResourceInjectionWithNonExistingTarget() {
118118
}
119119
}
120120

121+
@Test
122+
public void testLazyOptionalResourceInjectionWithNonExistingTarget() {
123+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
124+
bf.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
125+
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
126+
bpp.setBeanFactory(bf);
127+
bf.addBeanPostProcessor(bpp);
128+
RootBeanDefinition bd = new RootBeanDefinition(OptionalFieldResourceInjectionBean.class);
129+
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
130+
bf.registerBeanDefinition("annotatedBean", bd);
131+
132+
OptionalFieldResourceInjectionBean bean = (OptionalFieldResourceInjectionBean) bf.getBean("annotatedBean");
133+
assertNotNull(bean.getTestBean());
134+
try {
135+
bean.getTestBean().getName();
136+
fail("Should have thrown NoSuchBeanDefinitionException");
137+
}
138+
catch (NoSuchBeanDefinitionException ex) {
139+
// expected;
140+
}
141+
}
142+
121143

122144
public interface TestBeanHolder {
123145

@@ -136,6 +158,17 @@ public TestBean getTestBean() {
136158
}
137159

138160

161+
public static class OptionalFieldResourceInjectionBean implements TestBeanHolder {
162+
163+
@Autowired(required = false) @Lazy
164+
private TestBean testBean;
165+
166+
public TestBean getTestBean() {
167+
return this.testBean;
168+
}
169+
}
170+
171+
139172
public static class FieldResourceInjectionBeanWithCompositeAnnotation implements TestBeanHolder {
140173

141174
@LazyInject

0 commit comments

Comments
 (0)