From 1bd775f828ddb1f2919c2a57b1151dc3cca9f14c Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 31 Aug 2012 15:59:09 +0200 Subject: [PATCH] @Autowired-driven ObjectFactory/Provider resolution works in non-singleton beans as well Issue: SPR-9181 --- .../factory/config/DependencyDescriptor.java | 22 +++++++++++++++++++ .../support/DefaultListableBeanFactory.java | 8 ++----- ...wiredAnnotationBeanPostProcessorTests.java | 19 +++++++++++++++- ...njectAnnotationBeanPostProcessorTests.java | 20 +++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java index a54002c0b0..9ba567050c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java @@ -121,6 +121,24 @@ public class DependencyDescriptor implements Serializable { this.eager = eager; } + /** + * Copy constructor. + * @param original the original descriptor to create a copy from + */ + public DependencyDescriptor(DependencyDescriptor original) { + this.methodParameter = original.methodParameter; + this.field = original.field; + this.declaringClass = original.declaringClass; + this.methodName = original.methodName; + this.parameterTypes = original.parameterTypes; + this.parameterIndex = original.parameterIndex; + this.fieldName = original.fieldName; + this.required = original.required; + this.eager = original.eager; + this.nestingLevel = original.nestingLevel; + this.fieldAnnotations = original.fieldAnnotations; + } + /** * Return the wrapped MethodParameter, if any. @@ -156,6 +174,10 @@ public class DependencyDescriptor implements Serializable { } + /** + * Increase this descriptor's nesting level. + * @see MethodParameter#increaseNestingLevel() + */ public void increaseNestingLevel() { this.nestingLevel++; if (this.methodParameter != null) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index afabaac09d..fe7d2ebdd5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -21,14 +21,11 @@ import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectStreamException; import java.io.Serializable; - import java.lang.annotation.Annotation; import java.lang.ref.Reference; import java.lang.ref.WeakReference; - import java.security.AccessController; import java.security.PrivilegedAction; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -39,7 +36,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; - import javax.inject.Provider; import org.springframework.beans.BeansException; @@ -1031,9 +1027,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto private final String beanName; public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) { - this.descriptor = descriptor; - this.beanName = beanName; + this.descriptor = new DependencyDescriptor(descriptor); this.descriptor.increaseNestingLevel(); + this.beanName = beanName; } public Object getObject() throws BeansException { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java index 80e8bc7725..0e798b9e41 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java @@ -24,7 +24,6 @@ import java.lang.annotation.Target; import java.util.List; import java.util.Map; -import static org.junit.Assert.*; import org.junit.Test; import test.beans.ITestBean; import test.beans.IndexedTestBean; @@ -42,6 +41,8 @@ import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.util.SerializationTestUtils; +import static org.junit.Assert.*; + /** * Unit tests for {@link AutowiredAnnotationBeanPostProcessor}. * @@ -601,6 +602,22 @@ public final class AutowiredAnnotationBeanPostProcessorTests { bf.destroySingletons(); } + @Test + public void testObjectFactoryInjectionIntoPrototypeBean() { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(bf); + bf.addBeanPostProcessor(bpp); + bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryInjectionBean.class, false)); + bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class)); + + ObjectFactoryInjectionBean bean = (ObjectFactoryInjectionBean) bf.getBean("annotatedBean"); + assertSame(bf.getBean("testBean"), bean.getTestBean()); + ObjectFactoryInjectionBean anotherBean = (ObjectFactoryInjectionBean) bf.getBean("annotatedBean"); + assertNotSame(anotherBean, bean); + assertSame(bf.getBean("testBean"), anotherBean.getTestBean()); + } + @Test public void testObjectFactoryQualifierInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InjectAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InjectAnnotationBeanPostProcessorTests.java index 51ae86cd6c..76b754879d 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InjectAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InjectAnnotationBeanPostProcessorTests.java @@ -383,6 +383,26 @@ public class InjectAnnotationBeanPostProcessorTests { bf.destroySingletons(); } + @Test + public void testObjectFactoryInjectionIntoPrototypeBean() { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver()); + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(bf); + bf.addBeanPostProcessor(bpp); + bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class, false)); + RootBeanDefinition bd = new RootBeanDefinition(TestBean.class); + bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean")); + bf.registerBeanDefinition("testBean", bd); + bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class)); + + ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean"); + assertSame(bf.getBean("testBean"), bean.getTestBean()); + ObjectFactoryQualifierInjectionBean anotherBean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean"); + assertNotSame(anotherBean, bean); + assertSame(bf.getBean("testBean"), bean.getTestBean()); + } + @Test public void testObjectFactoryQualifierInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory();