@Lazy falls back to empty map/list/set for non-required collection dependency

Issue: SPR-15858
This commit is contained in:
Juergen Hoeller 2017-08-17 12:28:55 +02:00
parent 61cdc842e0
commit ec1eafc46f
2 changed files with 53 additions and 3 deletions

View File

@ -18,6 +18,11 @@ package org.springframework.context.annotation;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.aop.TargetSource; import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.framework.ProxyFactory;
@ -83,6 +88,16 @@ public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotat
public Object getTarget() { public Object getTarget() {
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null); Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
if (target == null) { if (target == null) {
Class<?> type = getTargetClass();
if (Map.class == type) {
return Collections.EMPTY_MAP;
}
else if (List.class == type) {
return Collections.EMPTY_LIST;
}
else if (Set.class == type || Collection.class == type) {
return Collections.EMPTY_SET;
}
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(), throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
"Optional dependency not present for lazy injection point"); "Optional dependency not present for lazy injection point");
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.context.annotation;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -59,6 +60,24 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests {
@Test @Test
public void testLazyResourceInjectionWithField() { public void testLazyResourceInjectionWithField() {
doTestLazyResourceInjection(FieldResourceInjectionBean.class); doTestLazyResourceInjection(FieldResourceInjectionBean.class);
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
RootBeanDefinition abd = new RootBeanDefinition(FieldResourceInjectionBean.class);
abd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
ac.registerBeanDefinition("annotatedBean", abd);
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setLazyInit(true);
ac.registerBeanDefinition("testBean", tbd);
ac.refresh();
FieldResourceInjectionBean bean = ac.getBean("annotatedBean", FieldResourceInjectionBean.class);
assertFalse(ac.getBeanFactory().containsSingleton("testBean"));
assertFalse(bean.getTestBeans().isEmpty());
assertNull(bean.getTestBeans().get(0).getName());
assertTrue(ac.getBeanFactory().containsSingleton("testBean"));
TestBean tb = (TestBean) ac.getBean("testBean");
tb.setName("tb");
assertSame("tb", bean.getTestBean().getName());
} }
@Test @Test
@ -114,7 +133,7 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests {
fail("Should have thrown NoSuchBeanDefinitionException"); fail("Should have thrown NoSuchBeanDefinitionException");
} }
catch (NoSuchBeanDefinitionException ex) { catch (NoSuchBeanDefinitionException ex) {
// expected; // expected
} }
} }
@ -131,12 +150,14 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests {
OptionalFieldResourceInjectionBean bean = (OptionalFieldResourceInjectionBean) bf.getBean("annotatedBean"); OptionalFieldResourceInjectionBean bean = (OptionalFieldResourceInjectionBean) bf.getBean("annotatedBean");
assertNotNull(bean.getTestBean()); assertNotNull(bean.getTestBean());
assertNotNull(bean.getTestBeans());
assertTrue(bean.getTestBeans().isEmpty());
try { try {
bean.getTestBean().getName(); bean.getTestBean().getName();
fail("Should have thrown NoSuchBeanDefinitionException"); fail("Should have thrown NoSuchBeanDefinitionException");
} }
catch (NoSuchBeanDefinitionException ex) { catch (NoSuchBeanDefinitionException ex) {
// expected; // expected
} }
} }
@ -152,9 +173,16 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests {
@Autowired @Lazy @Autowired @Lazy
private TestBean testBean; private TestBean testBean;
@Autowired @Lazy
private List<TestBean> testBeans;
public TestBean getTestBean() { public TestBean getTestBean() {
return this.testBean; return this.testBean;
} }
public List<TestBean> getTestBeans() {
return testBeans;
}
} }
@ -163,9 +191,16 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests {
@Autowired(required = false) @Lazy @Autowired(required = false) @Lazy
private TestBean testBean; private TestBean testBean;
@Autowired(required = false) @Lazy
private List<TestBean> testBeans;
public TestBean getTestBean() { public TestBean getTestBean() {
return this.testBean; return this.testBean;
} }
public List<TestBean> getTestBeans() {
return this.testBeans;
}
} }