Как вручную внедрить зависимости в bean-компонент в прослушивателе событий AfterBeanDiscovery (CDI) - PullRequest
0 голосов
/ 11 ноября 2018

Я использую 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, найденного в контексте. Как мне подойти к этому?

...