I\'m trying to use automatic dependency injection via Spring\'s @Configurable annotation w/ @Resource on the fields needing injection. This involved some setup, like passing
I found the reason; because custom beans register without order. If your bean was used before the Spring bean org.springframework.context.config.internalBeanConfigurerAspect
was loaded, then @Configurable autowire will not work.
And my solution is like below:
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
@EnableSpringConfigured
@ComponentScan(basePackages = "zhibo")
public class AppConfig extends WebMvcConfigurationSupport {
@Bean
public DemoProcessor demoProcessor() {
return new DemoProcessor();
}
}
public class DemoProcessor implements BeanPostProcessor,BeanDefinitionRegistryPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(System.err::println);
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
String[] beanDefinitionNames = registry.getBeanDefinitionNames();
Map<String, BeanDefinition> zhiboBeans = new LinkedHashMap<>();
//1. remove your beans. let spring's beans go ahead
Stream.of(beanDefinitionNames).forEach(beanName->{
BeanDefinition bd = registry.getBeanDefinition(beanName);
if(bd.getBeanClassName()!=null && bd.getBeanClassName().startsWith("zhibo.")) {
registry.removeBeanDefinition(beanName);
zhiboBeans.put(beanName, bd);
}
});
//2. register your beans again
zhiboBeans.forEach((k,v)->registry.registerBeanDefinition(k, v));
}
}
Can't spot anything obvious, so just a suggestion - have you tried using compile-time weaving? Hopefully that would lead to consistent results at runtime, although it can be a bit more hassle during development.
First I have to say that it is probably not a good idea to have resources, services or other beans injected into data model classes as dependencies. But that is a question of design.
To the usage of @Configurable I used it in cases where objects are instantiated from outside the Spring context - like custom tags in web applications, filters or servlets. The first way I tried to use them was by load time weaving like you do. That worked quite well but it had some drawbacks like hot code deployment while debugging did not work anymore.
I did also experience exactly the problem you describe and so I decided to switch from load time weaving to compile time. Therefor I installed the AJDT plugin in Eclipse and used the aspecjt support of Spring. That solved my problems.
It sounds like your deploy process is suspect. Can you do a deployment that works, then copy that off to a directory. Then do another deployment until you get one that doesn't work. (In either order) Then finally, use a tool like beyond compare to compare the two deployment directory structures and files, and see if there are any differences.
Good luck, nothing like a seemingly random problem to kill some productivity.
When the injection doesn't work, for whatever reason, there is no way for code to do any dependency check, so there is now error thrown.
Otherwise I can't see anything here that would indicate the random failure. Can you extract a simplified example to check?
To me it sounds like an occurence of a well known bug in Spring: http://jira.springframework.org/browse/SPR-5401.
Can it be that you are trying to use Configurable in several application contexts? In this case only one of them will be subject to dependency injection. Which one wins depends on which application context is the last one to be loaded.
Solution? None :-( There are no plans to fix this issue. That is at least what the SpringSource guy told at the JAX conference in Germany in April.