【问题标题】:Is there a way to re-inject / update injected bean fields?有没有办法重新注入/更新注入的 bean 字段?
【发布时间】:2016-06-23 13:43:12
【问题描述】:

我有一些 bean(多种类型,CDI、@Stateless 和 @Singleton bean)。他们的一些字段应该从数据库值中注入。

public class MyBean {

    @Inject
    @DbConfigValue(MyConfig.HOST)
    String host;
}

所以我添加了一个生产者使用的自定义@Qualifier (DbConfigValue)。生产者从数据库中读取并缓存配置值并将它们注入到 bean 中。

@Singleton
@Lock(LockType.READ)
public class Configuration {

    @Produces
    @Dependent
    @DbConfigValue
    public String getDbConfigValue(InjectionPoint point) {
        // get key for the config-value from qualifier-annotation of the injected field
        String key = point.getAnnotated().getAnnotation(DbConfigValue.class).value();
        // i have read+cached database config values in @PostConstruct before
        return cachedConfigValues.get(key);
    }
}

这适用于初始注入/bean 构造。一些网络教程建议使用这种方法。

现在,我认为假设配置值(如果存储在 DB 中)可能会在运行时更改是合理的。因此,每当管理员更改数据库配置值时,我目前都会触发 CDI 事件。

问题:有没有办法将值重新注入到已经初始化的 bean 实例的字段中?还是注入总是只与实例创建有关?

例如我有……与此类似:

public class MyEventListener {

    @Inject
    BeanManager beanManager;

    @Asynchronous
    public void onDbConfigValueChangedEvent (@Observes(during = TransactionPhase.AFTER_SUCCESS) DbConfigValueChangedEvent event) {
        try {
            // could be filtered by custom qualifier:
            Set<Bean<?>> beans = beanManager.getBeans(Object.class,new AnnotationLiteral<Any>() {});

            for (Bean<?> bean : beans) {
                Set<InjectionPoint> points = bean.getInjectionPoints();
                // What now? javax.enterprise.inject.spi.Bean is the 
                // bean-representation only. 
                // Can I somehow resolve the actual bean-instances here?
                // Then update Field via Reflection?
            }
        }
        catch(Exception e){
            // ...
        }
    }
}

我还考虑了DeltaSpike,它有一些注射控制方法。但是,我确实只找到了注入新 bean 实例的方法,甚至是使用 new-或 null-CreationalContexts (之后不再由 CDI 管理的 bean)

请注意:我知道我可以通过注入配置并显式获取每个请求的当前值来解决这个特定的用例,如下所示:

public class MyBean {

    @Inject
    Configuration config;

    public void someMethod(){
        String host = config.getConfig(MyConfig.HOST);
        // ...
    }
}

但是,我想知道一般问题:是否支持重新注入?或者如果没有,规范(CDI 或 Java EE)是否禁止它?

【问题讨论】:

    标签: java jakarta-ee dependency-injection cdi weld


    【解决方案1】:

    根据您的数据库的速度/速度,这可能会很昂贵。您可能会在生产者方法中利用一些缓存机制。 利用Instance 注入机制,延迟加载实际注入的bean。

    你的生产者(可能利用一些缓存来避免数据库调用所有的书)

    @Singleton
    @Lock(LockType.READ)
    public class Configuration {
    
        @Produces
        @RequestScoped //May fail if not in a request-context, but for ejb-calls, it is guaranteed to work as CDI has EJB Request Context
        @DbConfigValue
        public String getDbConfigValue(InjectionPoint point) {
            // get key for the config-value from qualifier-annotation of the injected field
            String key = point.getAnnotated().getAnnotation(DbConfigValue.class).value();
            // i have read+cached database config values in @PostConstruct before
            return cachedConfigValues.get(key);
        }
    }
    

    以及注入点:

    @SessionScoped
    public class MyBean {
    
        @Inject
        @DbConfigValue(MyConfig.HOST)
        private Instance<String> host;
    
        public void doSomething() {
            String myHost = host.get(); // of course will throw exception if value is failing. It will be resolved with every request.
        }
    }
    

    【讨论】:

    • 谢谢,有帮助,但不完全是我想要的:这要求在每个请求(每个 doSomething 调用)时进行注入(通过 Instance.get())。因此,它类似于我的上一个 sn-p (config.getConfig()),尽管您设法再次涉及 Producer 方法。但我宁愿只在触发 CDI 事件时重新注入。并问自己是否可以从 外部 (MyEventListener) into 重新注入所有正在运行的 bean-instances。
    • 理想情况下,生产者可以将值保存在缓存中,可以随时更新(当它发生变化时,只有生产者可以监听cdi事件,并更新缓存),并且所有实例都会获取更新。重新注入,imo 在这种情况下看起来不正确
    • 是的,只有在更改后才会缓存和更新值。事实上,对于这个特定问题,我什至已经将我的代码更改为与此类似的解决方案。但是,正如问题中提到的,我一般问自己是否支持 JavaEE/CDI 中的重新注入。只是出于好奇和可能的未来使用。那么,如果您说“在这种情况下不正确”,您是否了解重新注入的解决方案(针对不同的情况)?
    • 接近重新注入的唯一方法是使用Instance 具有一些小范围,这可以让您使用可能在上下文之间变化的不同bean实例
    • @florin 这取决于你的 bean 的范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 2011-04-20
    • 2013-11-15
    • 2020-11-25
    • 1970-01-01
    • 2013-12-12
    相关资源
    最近更新 更多