使用CDI扩展解决模糊的依赖关系

时间:2016-11-17 23:40:18

标签: dependency-injection cdi weld weld-se

我正在尝试修改现有的CDI扩展,它会创建自己的代理bean。现在,每个服务只创建一个代理。服务具有类似于应用程序范围的内容,因此始终只有一个服务实例。

我想要完成的是为每个注入点创建一个代理bean。我需要它们以存储特定于给定注入点的一些信息。如果同一服务有更多注入点,则会有更多代理bean,但仍然只有一个服务实例。但是,当我以这种方式改变行为时,Weld会抱怨模糊的依赖关系,因为它无法在两个完全相同的代理之间进行选择。

我该如何解决这个问题?基本上,我所做的是观察ProcessBean事件并为每个发现的bean的每个注入点创建一个新代理。然后我使用AfterBeanDiscovery#addBean方法将所有这些代理bean添加到容器中。我会以某种方式需要跳过最后一步并将它们手动注入其注入点,或者能够影响选择正确注入豆的决定。如果给出一个注入点和一个可以注入其中的模糊依赖项列表,我将能够根据其属性选择正确的依赖项。但我真的不知道是否有可能为Weld做出这个决定以及我该怎么做。

编辑:我想要做的就是实现类似于@Dependent的我自己的范围,但是使用代理我可以存储一些与给定注入点相关的其他信息。

EDIT2 :我最后通过创建一个包含特定注入点信息的新限定符来修复它。此限定符将添加到注入点及其代理。但这不是一个很好的解决方案,因为我必须用自己的实现替换注入点,这允许修改限定符集合。我觉得必须有一个更优雅的解决方案。如果你能想到,请告诉我。

1 个答案:

答案 0 :(得分:0)

首先,对于带有限定符的解决方案 - 这确实是正确的方法,但是在给定的情况下,我猜想有点多余的工作。

如果我的案例正确,你可以在一个扩展中使用两个观察者。

第一个会观察ProcessBeanAttributes阶段和veto()您不想要的原始豆。

void observePBA(@Observes ProcessBeanAttributes<?> bean) {
  // I used '?' as a type, so here you do your check for 
  // the actual bean class to know which one is it and whether
  // you actually want to veto such bean
  bean.veto();
}

另一个观察者就是你已经拥有的东西 - 在AfterBeanDiscovery#addBean中添加你自己的bean。

void observeABD(@Observes AfterBeanDiscovery abd) {
  // add your custom bean, assuming you have it prepared somewhere
  abd.addBean(myCustomBean);
}

这样,当容器启动时,您将删除原始bean并添加自定义bean。这样,Weld应该没有模棱两可的解决问题。