我有一个课程如下:
public class UserAuthenticator {
private static UserAuthenticator authenticator =
@Inject
private UserRepository userRepository;
@PostConstruct
public void init() {
List<User> allUsers = userRepository.findAll();
for (User user : allUsers) {
users.put(user.getEmail(), user.getPassword());
serviceKeys.put(user.getServiceKey(), user.getEmail());
}
}
public static UserAuthenticator getInstance() {
if (authenticator == null) {
authenticator = new UserAuthenticator();
}
return authenticator;
}
}
当我打电话
UserAuthenticator authenticator = UserAuthenticator.getInstance();
init()
方法未被调用且userRepository为null
我的网络应用程序在JBOSS EAP 6.3中运行。
这是如何引起的?如何解决?
答案 0 :(得分:6)
在Java EE应用程序中,不要单身思考。这是麻烦和混乱的唯一方法。相反,请考虑&#34; just create one&#34;。告诉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
,{{ 1}},@ManagedBean
,@WebServlet
,@WebListener
,@WebFilter
等。):
@Path
如果您非常肯定您需要一个静态方法来获取给定支持类的当前CDI托管bean实例,那么您应该通过@Inject
private UserAuthenticator userAuthenticator;
获取它,如下所示,而不是手动构建实例(assuming Java EE 7 / CDI 1.1 available):
BeanManager
用法:
@SuppressWarnings("unchecked")
public static <T> T getCurrentInstance(Class<T> beanClass) {
BeanManager beanManager = CDI.current().getBeanManager();
Bean<T> bean = (Bean<T>) beanManager.resolve(beanManager.getBeans(beanClass));
return (T) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
}
答案 1 :(得分:1)
我认为您不应该明确地致电UserAuthenticator.getInstance()
,而是将UserAuthenticator
定义为@ApplicationScoped,并通过您的应用服务器提供的DI获取实例(@Inject )。
UserAuthenticator should be then initialized properly.
答案 2 :(得分:0)
在对该类执行某些操作之前,不会调用@PostConstruct方法(例如:调用某些方法