我想要一个像这样的 Bean 和 SubBean:
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Component
public class SubBean implements ApplicationContextAware{
private Object parent;
public void setApplicationContext(ApplicationContext ctx){
this.parent = doSomeMagicToGetMyParent(ctx);
}
public Object getParent(){
return parent;
}
}
@Component
public class SomeBean implements InitializingBean{
@Resource
private SubBean sub;
public void afterPropertiesSet(){
Assert.isTrue(this == sub.getParent());
}
}
我想要实现的技巧是,SubBean 自动获取对其注入的 Bean 的引用。因为子 bean 的范围是原型,所以它将作为一个新实例注入到每个希望它被注入的父级中。
我的大想法是利用这种模式来编写一个可以注入到普通 bean 中的 LoggerBean。subbean 应该像 SLF4J Logger 一样工作。
那么有谁知道使这项工作的魔力吗?:)
编辑:我找到了使用自定义 BeanPostProcessor 执行此操作的解决方案:
@Component
public class DependencyInjectionAwareBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
for (Field f : bean.getClass().getFields()) {
if (f.getType().isInstance(IDependencyInjectionAware.class)) {
ReflectionUtils.makeAccessible(f);
try {
IDependencyInjectionAware diAware = (IDependencyInjectionAware) f.get(bean);
diAware.injectedInto(bean);
} catch (IllegalArgumentException e) {
ReflectionUtils.handleReflectionException(e);
} catch (IllegalAccessException e) {
ReflectionUtils.handleReflectionException(e);
}
}
}
return bean;
}
}
这是界面:
public interface IDependencyInjectionAware {
void injectedInto(Object parent);
}
这里有一个 Bean 使用它:
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Component
public class SomeAwareBean implements IDependencyInjectionAware {
private Object parent;
public void injectedInto(Object parent){
this.parent = parent;
}
public Object getParent(){
return parent;
}
}
这是一个使用正常 Bean 的测试,效果很好:
@Component
public class UsingBean implements InitializingBean {
@Resource
private SomeAwareBean b;
public void afterPropertiesSet(){
Assert.notNull(b); //works
Assert.isTrue(b.getParent() == this); //works
}
}
但是,当将其与通过 @Configurable 注入依赖项的普通类一起使用时,测试失败:
@Configurable
public class UsingPlainClass implements InitializingBean {
@Resource
private SomeAwareBean b;
public void afterPropertiesSet(){
Assert.notNull(b); //works
Assert.isTrue(b.getParent() == this); //fails because null is returned
}
}
所以这似乎让我想到了另一个问题:为什么我的自定义 BeanPostProcessor 不能在 @Configurable 类上运行?也许我毕竟不得不求助于 AspectJ ......
编辑:只是为了更新状态。毕竟我没有实现这个,因为这是过度工程......