如何为 class 我没有在 Java EE 中编写的单例对象定义?

How to define a singleton object for a class I didn't write in Java EE?

假设我想通过我的应用程序获得一个 not.my.Clock

public final class Clock {
  ... // business
}

我可以写下:

@Singleton
public class ClockProvider implements Supplier<Clock> {
  private Clock clock;
  @PostConstruct
  void init() {
    clock = ... ;
  }
  @Override
  public Clock get() {
    return clock;
  }
}

@RequestScoped
public class MyBean {
  @Inject ClockProvider clockProvider;
  // Use clockProvider.get()
}

如何为我的整个应用程序定义一个单例对象而不是单例提供程序,以便我可以编写以下代码? Java EE 7 教程 only speaks about singleton session bean, not singleton objects

@RequestScoped
public class MyBean {
  @Inject Clock clock;
  // Use clock directly: no clock-provider.
}

如果我必须用 Guice 来写,我会这样写:

bind(Clock.class).toInstance(...);

@Provides @Singleton Clock provideClock() {
  return ... ;
}

对于 CDI,您将希望选择 @ApplicationScoped(应用程序中的一个共享实例)而不是 @Singleton(您是说 EJB 一个?还是 CDI 一个?)。

然后你想对所有你想变成 beans 的 "non-beans" 做你想做的事 - 你告诉 CDI 如何生产这样的 bean。

@Produces
@ApplicationScoped
public Clock produceClock() {
  Clock clock = ... // any code you use to create or retrieve the instance
  return clock;
}

有了上面的内容,您就可以在您的代码中执行 @Inject Clock clock,这将调用此生产者以创建 bean。

如果您想阅读更多关于制作人的信息,请阅读 this chapter in CDI spec

您可以在 public Clock get() 方法上使用 @Produces@ApplicationScoped 注释来生成 Clock 单例:

@Produces
@ApplicationScoped
public Clock get() {
    // your code
}