Issue
I'm using Spring with AspectJ via compile-time weaving to use @Configurable spring annotation for objects non-managed by container.
Here is an example @Configurable-annotated object:
@Configurable(autowire = Autowire.BY_TYPE)
public class TestConfigurable {
private TestComponent component;
public TestComponent getComponent() {
return component;
}
@Autowired
public void setComponent(TestComponent component) {
this.component = component;
}
}
Component that I'm injecting into this object:
@Component
public class TestComponent {}
When I create TestConfigurable after context is created TestComponent injected there fine but when I'm doing so from @PostConstruct-annotated method it autowiring doesn't happen.
Component with @PostConstruct:
@Component
public class TestPostConstruct {
@PostConstruct
public void initialize() {
TestConfigurable configurable = new TestConfigurable();
System.out.println("In post construct: " + configurable.getComponent());
}
}
Application that I'm executing:
public class TestApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
applicationContext.registerShutdownHook();
TestConfigurable configurable = new TestConfigurable();
System.out.println("After context is loaded: " + configurable.getComponent());
}
}
Here is an output this application produces:
In post construct: null
After context is loaded: paulenka.aleh.roguelike.sandbox.TestComponent@fe18270
So is there any workaround to inject dependencies into @Configurable objects that are created inside @PostConstruct methods? All @Component-annotated beans are already in the context and autowiring is already done for them in time when @PostConstruct is called. Why Spring doesn't do autowiring here?..
Can post other configuration files (context and pom.xml) if they will help to resolve the problem.
Update 1: Looks like I found the cause of the problem. Objects annotated with @Configurable are initialized by AnnotationBeanConfigurerAspect which implements BeanFactoryAware. This aspect uses BeanFactory to initialize beans. Looks like @PostConstruct method of the TestPostConstruct object is executed before BeanFactory is set to AnnotationBeanConfigurerAspect. If logger set to debug the following message is printed to console: "BeanFactory has not been set on ...: Make sure this configurer runs in a Spring container. Unable to configure bean of type [...]. Proceeding without injection."
The question if there is any workaround is still open for me...
Solution
I found one workaround to this. To initialize AnnotationBeanConfigurerAspect aspect before @PostConstruct is executed you can add the following annotation to class with such @PostConstruct method:
@DependsOn("org.springframework.context.config.internalBeanConfigurerAspect")
Hope this information will be useful for someone.
Answered By - ixi