I have an app that I'm trying to use the latest Spring 3 conventions with annotation-based configurations, but I also have legacy classes that use constructor-injection. Based on the Spring documentation you're supposed to just call the method that creates that dependency and pass it into the constructor that needs it. That seems to work when the Configuration class is enhanced, but it would seem that if you @Import the Configuration class, it is not enhanced, so it can potentially inject non-autowired instances.
Specifically, if one of my repositories is constructor-injected into another bean and that repository is defined in the same Configuration class as the other bean (I know the Repositories should be in their own config class), then it is not wired with an injected EntityManager.
My Beans:
public class MyBean {
private ShouldBeSingleton d;
public @Autowired MyBean(ShouldBeSingleton d) { this.d = d; }
public ShouldBeSingleton getMyDependency() { return d; }
}
public class ShouldBeSingleton {
}
And two configuration classes like this:
@Configuration
public class MyImportedConfig {
@Bean public ShouldBeSingleton mySingleton() {
return new ShouldBeSingleton();
}
@Bean public MyBean myBean() {
return new MyBean(mySingleton());
}
}
@Configuration
@Import({MyImportedConfig.class})
public class MyConfig {
}
My main looks like this:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
MyBean bean = context.getBean(MyBean.class);
System.out.println("myInjectedSingleton=" + bean.getMyDependency());
System.out.println("mySingleton=" + context.getBean(ShouldBeSingleton.class));
}
If I load the MyImportedConfig.class, I get the correct output (i.e. the singleton class is the same if I call the method from within the MyImportedConfig):
myInjectedSingleton=test.ShouldBeSingleton@b42cbf
mySingleton=test.ShouldBeSingleton@b42cbf
But, if I change the AnnotationConfigApplicationContext to load MyConfig which imports MyImportedConfig this happens:
myInjectedSingleton=test.ShouldBeSingleton@a9ae05
mySingleton=test.ShouldBeSingleton@1dff3a2
Is this expected behavior? My current workaround is to just move anything that requires an EntityManager to be injected to another Configuration class, importing it, and then setting an @Autowired dependency in the Configuration class that needs to constructor-inject it.
I'm loading this in a AnnotationConfigWebApplicationContext and if I specify each Configuration class in the contextConfigLocation, then all the Configuration classes are properly enhanced, but this doesn't seem to use the "modular" @Import functionality.