je voudrais avoir un grain et un SubBean comme ceci:Get haricot mère dans le haricot prototype qui obtient injecté
@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());
}
}
L'astuce que je veux atteindre est que le SubBean obtient automagiquement une référence au Bean il s'est injecté dedans. Étant donné que la portée de la sous-classe est prototype, elle sera injectée en tant que nouvelle instance dans chaque parent qui veut l'injecter.
Ma grande idée est d'exploiter ce modèle pour écrire un LoggerBean qui peut être injecté dans des beans normaux. Le sous-sol devrait fonctionner comme un enregistreur SLF4J.
Alors, est-ce que quelqu'un sait la magie pour faire ce travail? :)
EDIT: Je ai trouvé une solution pour faire cela avec un BeanPostProcessor personnalisé:
@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;
}
}
Voici l'interface:
public interface IDependencyInjectionAware {
void injectedInto(Object parent);
}
Et ici un Bean en l'utilisant:
@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;
}
}
Voici un test avec un grain normal qui fonctionne parfaitement:
@Component
public class UsingBean implements InitializingBean {
@Resource
private SomeAwareBean b;
public void afterPropertiesSet(){
Assert.notNull(b); //works
Assert.isTrue(b.getParent() == this); //works
}
}
Bien que, lorsque vous utilisez la même chose avec une classe normale qui obtient les depedencies injectés par @Configurable, le test échoue:
@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
}
}
Cela semble donc m'avoir amené à une autre question: pourquoi mon BeanPostProcessor personnalisé ne fonctionnera-t-il pas sur des classes @Configurable? Peut-être que je dois recourir à AspectJ ... après tout
EDIT: Juste pour mettre à jour le statut. Je ne suis pas mettre en œuvre cette afterall parce que c'est overengineering ...