我正在尝试在一个按照单例方法实现的类中注入一个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方法一起使用,但没有运气。
答案 0 :(得分:21)
构建后发生注射。所以你不能在构造函数中使用它。
一种方法是添加一个带注释的@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 330依赖注入(guice等)link
你可以使用构造函数注入:
@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!");
}
}
答案 1 :(得分:4)
这不起作用,因为已经提到的注入将在调用构造函数之后执行。
在注入完成之后以及在其他地方提供对象本身之前,将调用带有@PostConstruct
注释的方法。
但是,仅当注入本身提供类的实例时,注入才有效。这是由于注入取决于代理。
因此,您需要在任何需要的地方注入MySingleton。为了确保它是一个单例,注释它@Singleton
,容器将为你工作。
Addiotnally要注意,CDI规范中的单例并不仅仅意味着一个实例化,而只代表@PostConstruct
的一个初始化。