以单例模式使用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
文件到位)? 我也尝试使用@Inject
和Logger
对象的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
初始化 。