【问题标题】:How to change instance (target) under CDI (Weld) proxy without proxy recreation如何在不重新创建代理的情况下更改 CDI(焊接)代理下的实例(目标)
【发布时间】:2019-03-24 15:00:48
【问题描述】:

如果某些属性发生更改,例如 db url 连接,我想刷新 bean(销毁、初始化)。问题是这个 bean 可能已经被注入到 CDI 容器中的其他 bean 中。我对此有两个想法: 1. 如果 bean 被代理 - 销毁此代理的目标,重新初始化此代理内的目标。 2. 对于@Singleton@Dependent bean,因为它们没有被代理,所以我可以将这样的bean 包装在代理中并执行与上述相同的操作。 我想将它包装在代理中的原因是,当属性更改并且我想重新创建真实对象时,我还应该知道所有依赖于我的 bean 的依赖 bean。 所以我的问题是: 1.如何在CDI中替换proxy里面的真实对象?或者 2. 如果我不想像上面解释的那样保留代理,如何为我的bean创建代理对象并将其重新注入CDI容器中的所有依赖bean?

这是我之前的问题: Re-inject CDI bean if some injected property changed

再次,我使用 CDI (Weld),而不是 Spring IoC,所以我不能使用 Spring 云配置中的 @RefreshScope,但我认为我的预期功能可以与使用自定义范围相似。

【问题讨论】:

  • CDI 为您的真实 bean/类“生成”一个代理,该代理在其他 bean 中注入,仅更改 bean/类中的值有什么问题?
  • 'Of' 应该是 'if'

标签: java dependency-injection proxy cdi weld


【解决方案1】:

对于@DependedSCoped bean,您可以使用 类 MyBean {

   @Inject
   private Instance<MYType> myTypeInst;

   // This will ensure, that the bean is always fresh created.
   // But the property value on the former instance will be lost
   // So the changable value has to be provided another way to the created bean
   public void do SomeThing(){
      MyType bean = myTypeInst.get();

      myTypeInst.destroy(bean);
   }
}

如果你使用@Depended 作用域的bean,那么你必须知道注入目标获得了它的实例,该实例专门用于这个bean,那么谁在更改值? @Dependend 范围是否适合您的用例?

不必提供自己的代理或侵入现有代理,只需为您的用例找到合适的范围并正确实施 bean。如果连接 url 可以更改,则管理连接的 bean 必须知道更改并重新创建连接,并且使用此 bean 的 bean 需要在每次使用时检索连接。

也许您可以提供您的用例的描述,那么我们也许可以为您提供更好的答案。

结论

随着用例变得清晰(参见下面的 cmets),它产生了实现自定义范围的意图,因为 CDI 似乎没有为此用例提供合适的范围。我建议尽可能尝试找到提供的 CDI 范围,并仅在必要时实施自定义范围,因为您必须注意 bean 的生命周期、范围的管理以及由您的范围管理的 bean 如何可以并将被应用程序使用。如果不小心实现自定义范围,可能会导致内存泄漏等问题,例如,如果您的 bean 在使用后没有正确丢弃。

【讨论】:

  • 我有集中配置服务器和客户端。客户端部分有一个调度程序,它从配置服务器获取属性。如果某些属性发生了变化(比如说数据库连接 url),那么客户端会生成事件。有一个监听器处理这个事件。一旦事件到来,监听器应该找到注入 url 的 bean 并重新注入这个属性。因为某些 DbConnection bean 使用了 url,所以它应该被销毁并使用新的 url 重新创建。当我说销毁和重新创建时,我的意思是在 bean 重新创建期间应该调用 PreDestroy 和 PostConstruct 逻辑。
  • 好的,现在我了解了用户案例。
  • 您确定不能使用 @Depended 以外的 CDI 范围实现这一目标吗? DBBean 的请求范围是否有效,这意味着 db 连接不会在请求中更改?每个 CDI Bean 请求都会获得一个新的 DBBean 实例。如果不是,那么使用 DBBean 的 CDIBean 应该在 DBBean 上调用 getConnection(),并且 DBBean 决定何时由于 url 更改而创建新连接。该事件在 DBBean 使用的 @ApplicationScoped Config bean 上设置属性,DBBean 在实例化时检索每个请求的连接 url。
  • 是的,youre right. But there is one small additional requirement I forgot to tell: Im 为基于 CDI 的 Web 应用程序编写通用库。他们会将其作为 Maven 依赖项包含在内。 DBBean 是 Web 应用程序中使用的示例 bean。因此,在 lib 实现期间,我应该依靠最通用的方式来处理属性更改事件。我认为自定义范围创建将是我的最佳解决方案。
  • 如何为不同的范围实现生产者,这些范围符合@RequestScopedDBConnection 等等?另一种方法是从 bean 管理器中动态添加/删除所有 bean,我认为这只会影响新注入的 bean 而尚未注入的 bean。我会寻找这样的实现,我想我看到了一个
猜你喜欢
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 2020-07-15
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多