Почему конструктор класса CDI 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
  }
}

В основном это работает нормально. Howeger, по крайней мере, когда я запускаю это в WebSphere 8.5, конструктор MySingleton вызывается дважды, в результате чего выводится как

my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.

Я планировал сделать какую-то дорогостоящую инициализацию в конструкторе, которая, очевидно, будет выполнена дважды.

Я полагаю, что один из вызовы конструктора предназначены для создания некоторого прокси-сервера для фактического экземпляра "worker". Но как я могу избежать того, чтобы мой код инициализации выполнялся дважды? "Решение" сделать ленивую инициализацию во всех методах MySingleton не очень привлекательно.

2 3

2 ответа:

Конструктор управляемых бобов может быть вызван контейнером также для создания прокси-серверов. Поэтому для любой "реальной" инициализации Java EE предоставляет аннотацию @PostConstruct. В бобе @ApplicationScoped метод с аннотацией @PostConstruct вызывается контейнером ровно один раз:

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

Вывод:

my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.
my.package.MySingleton@e51e26d1 initd.

Связанный Вопрос: зачем использовать @PostConstruct?

Это прокси-объект javassist, созданный для вашего синглтона. Одноэлементный контруктор должен вызываться только при создании реального объекта.