想象一下以下简化的DI模型:
@ApplicationScoped
public class A {
private B b;
@Inject
public A(B b) {
this.B = b;
}
}
@ApplicationScoped
public class B {
private C c;
@Inject
public B(C c) {
this.C = c;
}
}
@ApplicationScoped
public class C {
@PostConstruct
public void start() {
// processing that should begin on startup
}
}
假设我希望在部署完成时调用C#start
。通常在线建议的模式是here,但解决方案:1)添加太多样板,2)为扩展添加新的文本文件,3)使用{{1}的作弊单独触发toString
代理实例化下面的实际B
bean,然后触发B
代理等。
从CDI 1.1开始,将以下方法添加到C
也是一种解决方案:
A
这解决了上面描述的前两个问题,但我仍然需要在public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
B.toString();
}
上调用一个虚方法,以便触发实例化/注入链并最终调用B
带注释的方法{{ 1}}。
我错过了这个问题的清洁解决方案吗? CDI 2.0能解决这个问题吗?
答案 0 :(得分:0)
您无法选择急切初始化,您必须选择一些“解决方法”。 CDI没有定义bean init是懒惰还是渴望,而且懒惰在大多数时候都更有意义,Weld也是这样。
您最好的选择与article you mentioned建议的类似。例如。设置一个扩展,樱桃挑选你想要急切初始化的bean并初始化它们并加上一个(无害的)方法。
显然,这只适用于部署中的几个bean(我认为最多使用应用程序范围的bean),因此开销不会太大(如果有的话)。还有一些额外的样板,但是你不必写那么多行就可以了。
为了使它更好,您可以让所有bean使用默认的ping()
方法实现虚拟接口,并从扩展中调用该方法 - 只是为了避免调用toString()
。