在Java EE应用程序中,不要单身思考.这只是麻烦和困惑的秘诀.相反,请在“
just create one”中思考.告诉Java EE容器只创建指定类的一个实例,应用程序范围,并通过Java EE容器提供的工具获取实例.您的具体问题是由于您使用new运算符手动创建类的实例而没有手动执行注入和post构造调用,如下面的技术正确但概念上错误的示例:
authenticator = new UserAuthenticator();
authenticator.userRepository = new UserRepository();
authenticator.init();
换句话说,您错误地期望new运算符神奇地识别bean管理和依赖注入相关的注释.
正确的方法取决于您要指出的负责创建和管理指定类的实例的方法.如果它是CDI,那么只需告诉它使用@Named @ApplicationScoped在应用程序范围内创建一个支持bean类的托管bean实例.
import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;
@Named
@ApplicationScoped
public class UserAuthenticator {}
它将只创建一次,并且可以通过@Inject在任何其他Java EE托管工件中使用,如下所示(读取:在@Named,@ Stateless,@ ManverBean,@ WebServlet,@ WebListener,@ WebFilter,@ Path注释的任何其他类中)等等..):
@Inject
private UserAuthenticator userAuthenticator;
如果您非常肯定需要一个静态方法来获取给定支持类的当前CDI托管bean实例,那么您应该通过BeanManager获取它,如下所示,而不是手动构建实例(assuming Java EE 7 / CDI 1.1 available):
@SuppressWarnings("unchecked")
public static T getCurrentInstance(Class beanClass) {
BeanManager beanManager = CDI.current().getBeanManager();
Bean bean = (Bean) beanManager.resolve(beanManager.getBeans(beanClass));
return (T) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
}
用法:
UserAuthenticator userAuthenticator = YourCDIUtil.getCurrentInstance(UserAuthenticator.class);
// ...
也可以看看: