以单例模式使用CDI

时间:2013-02-28 14:43:32

标签: java dependency-injection singleton 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方法一起使用,但没有运气。

2 个答案:

答案 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的一个初始化