From bff2bf2cdb6f6fce6e1f54477e5bf88cb05bb3f6 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 3 Sep 2014 00:28:05 +0200 Subject: [PATCH] AbstractAutowireCapableBeanFactory avoids early FactoryBean instantiation on currently created configuration bean Issue: SPR-12141 (cherry picked from commit 4432c41) --- .../AbstractAutowireCapableBeanFactory.java | 3 +- ...tionWithFactoryBeanAndAutowiringTests.java | 30 +++++-------- .../PropertySourceAnnotationTests.java | 43 ++++++++++++++++++- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 82605fd327c..b0525263907 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -832,7 +832,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (bw != null) { return (FactoryBean) bw.getWrappedInstance(); } - if (isSingletonCurrentlyInCreation(beanName)) { + if (isSingletonCurrentlyInCreation(beanName) || + (mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) { return null; } Object instance = null; diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanAndAutowiringTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanAndAutowiringTests.java index 81e7b1af66b..6f4602bd459 100755 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanAndAutowiringTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanAndAutowiringTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,9 @@ package org.springframework.context.annotation; import org.junit.Test; -import org.springframework.beans.factory.BeanCreationException; + import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.util.Assert; /** @@ -35,8 +32,7 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests { @Test public void withConcreteFactoryBeanImplementationAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(ConcreteFactoryBeanImplementationConfig.class); ctx.refresh(); @@ -44,8 +40,7 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests { @Test public void withParameterizedFactoryBeanImplementationAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(ParameterizedFactoryBeanImplementationConfig.class); ctx.refresh(); @@ -53,8 +48,7 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests { @Test public void withParameterizedFactoryBeanInterfaceAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(ParameterizedFactoryBeanInterfaceConfig.class); ctx.refresh(); @@ -62,31 +56,27 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests { @Test public void withNonPublicParameterizedFactoryBeanInterfaceAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(NonPublicParameterizedFactoryBeanInterfaceConfig.class); ctx.refresh(); } - @Test(expected=BeanCreationException.class) + @Test public void withRawFactoryBeanInterfaceAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(RawFactoryBeanInterfaceConfig.class); ctx.refresh(); } - @Test(expected=BeanCreationException.class) + @Test public void withWildcardParameterizedFactoryBeanInterfaceAsReturnType() { - AnnotationConfigApplicationContext ctx = - new AnnotationConfigApplicationContext(); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(WildcardParameterizedFactoryBeanInterfaceConfig.class); ctx.refresh(); } - } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java index a261ae413b1..a6492e970c7 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.core.env.Environment; import org.springframework.core.env.MutablePropertySources; import org.springframework.tests.sample.beans.TestBean; @@ -99,7 +100,7 @@ public class PropertySourceAnnotationTests { } } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void withUnresolvablePlaceholder() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(ConfigWithUnresolvablePlaceholder.class); @@ -124,6 +125,16 @@ public class PropertySourceAnnotationTests { System.clearProperty("path.to.properties"); } + @Test + public void withResolvablePlaceholderAndFactoryBean() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(ConfigWithResolvablePlaceholderAndFactoryBean.class); + System.setProperty("path.to.properties", "org/springframework/context/annotation"); + ctx.refresh(); + assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p1TestBean")); + System.clearProperty("path.to.properties"); + } + @Test(expected = IllegalArgumentException.class) public void withEmptyResourceLocations() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); @@ -201,6 +212,7 @@ public class PropertySourceAnnotationTests { @Configuration @PropertySource(value="classpath:${unresolvable:org/springframework/context/annotation}/p1.properties") static class ConfigWithUnresolvablePlaceholderAndDefault { + @Inject Environment env; @Bean @@ -213,6 +225,7 @@ public class PropertySourceAnnotationTests { @Configuration @PropertySource(value="classpath:${path.to.properties}/p1.properties") static class ConfigWithResolvablePlaceholder { + @Inject Environment env; @Bean @@ -222,10 +235,37 @@ public class PropertySourceAnnotationTests { } + @Configuration + @PropertySource(value="classpath:${path.to.properties}/p1.properties") + static class ConfigWithResolvablePlaceholderAndFactoryBean { + + @Inject Environment env; + + @Bean + public FactoryBean testBean() { + final String name = env.getProperty("testbean.name"); + return new FactoryBean() { + @Override + public Object getObject() { + return new TestBean(name); + } + @Override + public Class getObjectType() { + return TestBean.class; + } + @Override + public boolean isSingleton() { + return false; + } + }; + } + } + @Configuration @PropertySource(name="p1", value="classpath:org/springframework/context/annotation/p1.properties") static class ConfigWithExplicitName { + @Inject Environment env; @Bean @@ -238,6 +278,7 @@ public class PropertySourceAnnotationTests { @Configuration @PropertySource("classpath:org/springframework/context/annotation/p1.properties") static class ConfigWithImplicitName { + @Inject Environment env; @Bean