Spring's JavaConfig and CustomScopeConfigurer issue
java, spring
Solution
Copied from Spring @Bean javadoc:
BeanFactoryPostProcessor-returning @Bean methods
Special consideration must be taken for @Bean methods that return Spring BeanFactoryPostProcessor (BFPP) types. Because BFPP objects must be instantiated very early in the container lifecycle, they can interfere with processing of annotations such as @Autowired, @Value, and @PostConstruct within @Configuration classes. To avoid these lifecycle issues, mark BFPP-returning @Bean methods as static. For example:
@Bean
public static PropertyPlaceholderConfigurer ppc() {
// instantiate, configure and return ppc ...
}
By marking this method as static, it can be invoked without causing instantiation of its declaring @Configuration class, thus avoiding the above-mentioned lifecycle conflicts. Note however that static @Bean methods will not be enhanced for scoping and AOP semantics as mentioned above. This works out in BFPP cases, as they are not typically referenced by other @Bean methods. As a reminder, a WARN-level log message will be issued for any non-static @Bean methods having a return type assignable to BeanFactoryPostProcessor.
Problem
I'm seeing some odd behavior, I was hoping someone here can shine some light on the issue. Let me start by describing my setup. First, a simple data object ``` public class Apple { private String name; public Apple withName(String name) { this.name = name; return this; } public String getName() { return name; } } ``` And a test class.. ``` @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={TestConfig.class}) public class AppleTest { @Autowired private Apple apples; @Test public void simpleTest() { System.out.println("OBJ: "+apples); } } ``` The config is as follows ``` @Configuration public interface ConfigInterface { public Apple getApple(); } ``` With an implementing class ``` @Configuration @Import(AbstractTestConfig.class) public class TestConfig implements ConfigInterface { public Apple getApple() { return new Apple().withName("Granny apples"); } } ``` With the config dependency... ``` @Configuration public class AbstractTestConfig { @Autowired ConfigInterface conf; @Bean Apple myTestApple() { return conf.getApple(); } } ``` All of this works great. I run the test, I see the output I expect. But then I throw a spanner into the wheel and modify AbstractTestConfig to look as follows. ``` @Configuration public class AbstractTestConfig { @Autowired ConfigInterface conf; @Bean Apple myTestApple() { return conf.getApple(); } // NEW CODE @Bean CustomScopeConfigurer scopeConfigurer() { return new CustomScopeConfigurer(); } } ``` And all of a sudden the `@Autowired` object `conf` is null when it is required to construct the `Apple` bean. Even more odd, if I move the `CustomScopeConfigurer` bean to the `TestConfig` class, then it works. Is there something I don't know about scopes or the `CustomScopeConfigurer` object in particular?