Java 运行时重新加载CDI上下文

Java 运行时重新加载CDI上下文,java,ejb,cdi,java-ee-8,Java,Ejb,Cdi,Java Ee 8,我有基于CDI的应用程序。在运行时,我的应用程序生成导致bean重新加载的自定义事件。Bean重载意味着遍历所有Bean并重新初始化已经注入的Bean。重新初始化应该注意bean的依赖关系。例如: class BeanA { String url; @PostConstruct void init(){ url = UrlFactory.getNewUrl() } } class BeanB { @Inject BeanA beanA; @PostConstruct

我有基于CDI的应用程序。在运行时,我的应用程序生成导致bean重新加载的自定义事件。Bean重载意味着遍历所有Bean并重新初始化已经注入的Bean。重新初始化应该注意bean的依赖关系。例如:

class BeanA {

 String url;

 @PostConstruct
 void init(){
  url = UrlFactory.getNewUrl()
 }
}

class BeanB {

 @Inject
 BeanA beanA;

 @PostConstruct
 void init(){
  url = beanA.getUrl();
  doSomethingWith(url);
 }
因此,当事件发生时,BeanA和BeanB应该按照严格的顺序重新初始化,所以在BeanB重新初始化期间,BeanB已经知道在BeanA中初始化的新url。 是否可以在运行时使用CDI中已有的工具(类似于Spring中的AutowireCapableBeanFactory)? 我发现EJB已经有@DependsOn注释,能够在应用程序启动期间构建bean顺序

我提出的最强大的解决方案是在应用程序启动期间侦听一个CDI事件,收集所有bean并构建依赖关系图,在重新加载期间遍历此图并进行重新初始化。恐怕我没有意识到我可能会遇到很多陷阱(比如循环依赖、延迟初始化(在本例中可能根本不起作用)以及许多其他我不知道的陷阱,因为我对CDI容器内部的工作方式没有很好的理解)


有没有其他现有技术可以真正解决我的问题?

首先,创建一个生产者方法,
@生成您的
字符串
-键入
url
值(可能创建一个
@url
限定符注释来进一步识别它)。在
@Dependent
范围内生成此文件。比如:

@Produces @Dependent @URL private static final String produceUrl() {
  return UrlFactory.getNewUrl();
}
现在,只要有人执行
@Inject@URL private String URL
操作,他们就会从您的
UrlFactory
中获得一个新的
String
URL表示

更重要的是,任何人只要
@Inject@URL私有提供者urlProvider
他们将获得一个
提供者
,调用该提供者的
get()
方法时,将返回最新和最大的URL值

如果你看得对的话,这可能就是你所需要的

如果它不是您所需要的全部,那么让
BeanA
执行以下操作:

@Inject
@URL
private Provider<String> urlProvider;
每次都会得到一个新的
字符串

如果您已经这样做了,那么您可以将
BeanA
添加到您的observer方法中,并将其交给您:

private static final void onEvent(@Observes final YourEvent event, final BeanA beanA) {
  final String url = beanA.getUrl(); // latest and greatest      
}

尝试使用
提供程序
实例
:更多详细信息需要注意的一点是CDI注入代理,它不注入实际实例。当代理上的方法被调用时,CDI代理将您路由到正确的bean实例。感谢Laird的回答。但是,如果UrlFactory也在侦听YouEvent并从该事件获取新的url呢?在这种情况下,当事件发生时,UrlFactory应该获得新的url,并且只有在获得新的url之后才能在依赖bean中使用。是否有可能告诉我们:BeanA依赖于UrlFactory,BeanB依赖于UrlFactory,以便在BeanA和BeanB重新初始化之前允许UrlFactory重新初始化其状态?
private static final void onEvent(@Observes final YourEvent event, final BeanA beanA) {
  final String url = beanA.getUrl(); // latest and greatest      
}