Я использую CDI 1.2 (Weld 2.3.5) и хочу вручную создать экземпляр компонента и внедрить его зависимости во время прослушивателя события AfterBeanDiscovery
. Я ожидаю, что это позволит мне гарантировать, что его инициализация будет предшествовать @PostConstruct
инициализации других bean-компонентов в контейнере развертывания.
Однако я хочу использовать компонент, объявленный через @Produces
, в качестве зависимости для компонента, который я пытаюсь создать. Согласно документу API BeanManager мне не разрешается вызывать метод BeanManager.getReference()
во время события AfterBeanDiscovery
. Так что я немного застрял; Я не уверен, смогу ли я / как извлечь / использовать зависимость, объявленную в контейнере в качестве параметра, при создании моего bean-компонента в моем слушателе ABD.
Пока у меня есть следующее:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
Я все еще учусь тому, как наилучшим образом использовать события и слушателей JEE / CDI, так что, возможно, это неправильный подход. Есть ли возможность легально делать то, что я надеюсь сделать? Есть ли способ использовать / получить доступ к экземпляру bean-объекта, контролируемого CDI, из прослушивателя событий ABD?
Я ищу поддержку нескольких @Produces CustomConfig
bean-компонентов и генерирую CDICustomConfig
для каждого экземпляра bean-компонента CustomConfig, найденного в контексте. Как мне подойти к этому?