以单例模式使用CDI

我正在尝试在一个按照单例方法实现的类中注入一个logger对象。

代码几乎看起来像这样:

Logger类:

 public class LoggerFactory { @Produces public Logger getLogger(InjectionPoint caller){ return Logger.getLogger(caller.getMember().getDeclaringClass().getName()); } } 

然后我创建一个需要logger并实现Singleton模式的类:

 public class MySingleton{ @Inject private Logger logger; private MySingleton instance; /* * Private constructor for singleton implementation */ private MySingleton(){ logger.info("Creating one and only one instance here!"); } public MySingleton getInstance(){ if(instance == null) { instance = new MySingleton(); } return instance; } 

}

如果我运行代码(在Glassfish 3.1.2.2上),我会在尝试使用记录器后立即获得NPE。 我做错了什么( beans.xml文件到位)? 我也尝试使用@InjectLogger对象的setter方法,但没有运气。

注射在构建后发生。 所以你不能在构造函数中使用它。

一种方法是添加一个注释@PostConstruct的方法,该方法可以在注入后调用。

 @PostConstruct public void init() { logger.info("Creating one and only one instance here!"); } 

在旁注我认为你正以错误的方式解决问题。 CDI有一个很好的单例支持

创建一个注释@Singleton的类

 @Singleton public class MySingleton { @Inject Logger logger; @PostConstruct public void init() { logger.info("Creating one and only one instance here!"); } } 

以上假设您正在使用CDI for java ee(JSR-299)。

如果您正在使用JSR 330dependency injection(guice等) 链接

你可以使用构造函数注入:

 @Singleton public class MySingleton { private final Logger logger; @Inject public MySingleton (Logger logger) { this.logger = logger; logger.info("Creating one and only one instance here!"); } } 

这不起作用,因为已经提到过的注入将在调用构造函数之后执行。

在注入完成之后以及在其他地方提供对象本身之前,将调用使用@PostConstruct注释的方法。

但是,仅当注入本身提供类的实例时,注入才有效。 这是由于注射取决于代理。

因此,您需要在任何需要的地方注入MySingleton。 为了确保它是一个单例,注释它@Singleton ,容器将为你工作。

另外要注意的是,CDI规范中的单例并不仅仅意味着一个实例化 ,而只是一个@PostConstruct 初始化