急切的 CDI bean 实例化的干净解决方案
Clean solution for eager CDI bean instantiation
设想以下简化的 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) 求助于使用 toString
仅触发 B
代理来实例化实际的 B
bean,其下将依次触发 C
代理等
从CDI 1.1开始,在A
中加入如下方法也是一种解决方法:
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
B.toString();
}
这解决了上面描述的前两个问题,但我仍然需要在 B
上调用一个虚拟方法,以便触发 instantiation/injection 链并最终调用带注释的 @PostConstruct
C
.
的方法
我是否缺少针对此问题的更简洁的解决方案? CDI 2.0 是否解决了这个问题?
没有选项可以 select 进行预初始化,您必须选择一些 "workaround"。 CDI 没有定义 bean init 应该是惰性的还是急切的,并且由于大多数时候惰性更有意义,Weld 就是那样。
您最好的选择与 article you mentioned 所建议的类似。例如。设置一个扩展,挑选你想要急切初始化的 beans 并初始化它们并在它们上调用一个(无害的)方法。
显然,这仅对部署中的少数 bean 有意义(我认为最多是应用范围的 beans),因此不会有太多开销(如果有的话)。有一些额外的样板文件,但并不是说你必须写那么多行才能完成这项工作。
为了让它更好,您可以让所有 bean 使用默认 ping()
方法实现一个虚拟接口,并从扩展中调用该方法 - 这样您就可以避免调用 toString()
.
设想以下简化的 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) 求助于使用 toString
仅触发 B
代理来实例化实际的 B
bean,其下将依次触发 C
代理等
从CDI 1.1开始,在A
中加入如下方法也是一种解决方法:
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
B.toString();
}
这解决了上面描述的前两个问题,但我仍然需要在 B
上调用一个虚拟方法,以便触发 instantiation/injection 链并最终调用带注释的 @PostConstruct
C
.
我是否缺少针对此问题的更简洁的解决方案? CDI 2.0 是否解决了这个问题?
没有选项可以 select 进行预初始化,您必须选择一些 "workaround"。 CDI 没有定义 bean init 应该是惰性的还是急切的,并且由于大多数时候惰性更有意义,Weld 就是那样。
您最好的选择与 article you mentioned 所建议的类似。例如。设置一个扩展,挑选你想要急切初始化的 beans 并初始化它们并在它们上调用一个(无害的)方法。
显然,这仅对部署中的少数 bean 有意义(我认为最多是应用范围的 beans),因此不会有太多开销(如果有的话)。有一些额外的样板文件,但并不是说你必须写那么多行才能完成这项工作。
为了让它更好,您可以让所有 bean 使用默认 ping()
方法实现一个虚拟接口,并从扩展中调用该方法 - 这样您就可以避免调用 toString()
.