为什么CDI bean类的构造函数不止一次被调用

Ger*_*ard 5 constructor java-ee cdi managed-bean

我用@ApplicationScoped注释了一个类.使用@Inject,我将这个类的实例注入到几个@RequestScopded JAX-RS服务中:

@ApplicationScoped
public class MySingleton {
  MySingleton() {
    System.out(this + " created.");
  }
}

@RequestScoped
public class MyRS {
  @Inject MySingleton mySingleton;
  public void someMethod() {
    // do something with mySingleton
  }
}
Run Code Online (Sandbox Code Playgroud)

基本上这很好用.Howeger,至少当我在WebSphere 8.5中运行它时,MySingleton的构造函数被调用两次,导致输出像

my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.
Run Code Online (Sandbox Code Playgroud)

我打算在构造函数中做一些昂贵的初始化,显然会执行两次.

我相信其中一个构造函数调用是为实际的"worker"实例生成某种代理.但是如何避免我的初始化代码执行两次?在MySingleton的所有方法中进行延迟初始化的"解决方案"并不是很有吸引力.

Ger*_*ard 8

托管bean的构造函数也可以由容器调用以创建代理.对于任何"真正的"初始化,Java EE因此提供注释@PostConstruct.在@ApplicationScoped bean中,使用@PostConstruct注释的方法仅由容器调用一次:

@ApplicationScoped
public class MySingleton {
  MySingleton() {
    System.out(this + " created.");
  }
  @PostConstruct
  init() {
    System.out(this + " initd.");
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.
my.package.MySingleton@e51e26d1 initd.
Run Code Online (Sandbox Code Playgroud)

相关问题:为什么要使用@PostConstruct?