Skip to content

Commit ec1eafc

Browse files
committed
@lazy falls back to empty map/list/set for non-required collection dependency
Issue: SPR-15858
1 parent 61cdc84 commit ec1eafc

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.Method;
21+
import java.util.Collection;
22+
import java.util.Collections;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Set;
2126

2227
import org.springframework.aop.TargetSource;
2328
import org.springframework.aop.framework.ProxyFactory;
@@ -83,6 +88,16 @@ public boolean isStatic() {
8388
public Object getTarget() {
8489
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
8590
if (target == null) {
91+
Class<?> type = getTargetClass();
92+
if (Map.class == type) {
93+
return Collections.EMPTY_MAP;
94+
}
95+
else if (List.class == type) {
96+
return Collections.EMPTY_LIST;
97+
}
98+
else if (Set.class == type || Collection.class == type) {
99+
return Collections.EMPTY_SET;
100+
}
86101
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
87102
"Optional dependency not present for lazy injection point");
88103
}

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

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 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.
@@ -18,6 +18,7 @@
1818

1919
import java.lang.annotation.Retention;
2020
import java.lang.annotation.RetentionPolicy;
21+
import java.util.List;
2122

2223
import org.junit.Test;
2324

@@ -59,6 +60,24 @@ private void doTestLazyResourceInjection(Class<? extends TestBeanHolder> annotat
5960
@Test
6061
public void testLazyResourceInjectionWithField() {
6162
doTestLazyResourceInjection(FieldResourceInjectionBean.class);
63+
64+
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
65+
RootBeanDefinition abd = new RootBeanDefinition(FieldResourceInjectionBean.class);
66+
abd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
67+
ac.registerBeanDefinition("annotatedBean", abd);
68+
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
69+
tbd.setLazyInit(true);
70+
ac.registerBeanDefinition("testBean", tbd);
71+
ac.refresh();
72+
73+
FieldResourceInjectionBean bean = ac.getBean("annotatedBean", FieldResourceInjectionBean.class);
74+
assertFalse(ac.getBeanFactory().containsSingleton("testBean"));
75+
assertFalse(bean.getTestBeans().isEmpty());
76+
assertNull(bean.getTestBeans().get(0).getName());
77+
assertTrue(ac.getBeanFactory().containsSingleton("testBean"));
78+
TestBean tb = (TestBean) ac.getBean("testBean");
79+
tb.setName("tb");
80+
assertSame("tb", bean.getTestBean().getName());
6281
}
6382

6483
@Test
@@ -114,7 +133,7 @@ public void testLazyResourceInjectionWithNonExistingTarget() {
114133
fail("Should have thrown NoSuchBeanDefinitionException");
115134
}
116135
catch (NoSuchBeanDefinitionException ex) {
117-
// expected;
136+
// expected
118137
}
119138
}
120139

@@ -131,12 +150,14 @@ public void testLazyOptionalResourceInjectionWithNonExistingTarget() {
131150

132151
OptionalFieldResourceInjectionBean bean = (OptionalFieldResourceInjectionBean) bf.getBean("annotatedBean");
133152
assertNotNull(bean.getTestBean());
153+
assertNotNull(bean.getTestBeans());
154+
assertTrue(bean.getTestBeans().isEmpty());
134155
try {
135156
bean.getTestBean().getName();
136157
fail("Should have thrown NoSuchBeanDefinitionException");
137158
}
138159
catch (NoSuchBeanDefinitionException ex) {
139-
// expected;
160+
// expected
140161
}
141162
}
142163

@@ -152,9 +173,16 @@ public static class FieldResourceInjectionBean implements TestBeanHolder {
152173
@Autowired @Lazy
153174
private TestBean testBean;
154175

176+
@Autowired @Lazy
177+
private List<TestBean> testBeans;
178+
155179
public TestBean getTestBean() {
156180
return this.testBean;
157181
}
182+
183+
public List<TestBean> getTestBeans() {
184+
return testBeans;
185+
}
158186
}
159187

160188

@@ -163,9 +191,16 @@ public static class OptionalFieldResourceInjectionBean implements TestBeanHolder
163191
@Autowired(required = false) @Lazy
164192
private TestBean testBean;
165193

194+
@Autowired(required = false) @Lazy
195+
private List<TestBean> testBeans;
196+
166197
public TestBean getTestBean() {
167198
return this.testBean;
168199
}
200+
201+
public List<TestBean> getTestBeans() {
202+
return this.testBeans;
203+
}
169204
}
170205

171206

0 commit comments

Comments
 (0)