14

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

代码几乎是这样的:

Logger班级:

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

然后我创建一个需要记录器并实现单例模式的类:

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的 setter 方法,Logger但没有运气。

4

2 回答 2

24

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

一种方法是添加一个注解 @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 等)链接

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

@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!");
    }
}
于 2013-02-28T14:55:31.137 回答
4

这是行不通的,因为如前所述,注入将在调用构造函数之后执行。

@PostConstruct在注入完成之后并且在对象本身将被提供给其他地方之前调用带有注释的方法。

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

因此,您需要在任何需要的地方注入您的 MySingleton。为确保它是单例,请对其进行注释,@Singleton容器将为您解决问题。

Addiotnally beware, that singleton in terms of CDI spec does not mean only one instantiation, but rather only one initialiation of @PostConstruct.

于 2013-02-28T14:56:20.887 回答