我有一个类如下:
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
我的 Web 应用程序在 JBOSS EAP 6.3 中运行。
这是怎么引起的,我该如何解决?
最佳答案
在 Java EE 应用程序中,不要考虑单例。那只会带来麻烦和困惑。相反,请考虑“just create one”。告诉 Java EE 容器仅在应用程序范围内创建指定类的一个实例,并通过 Java EE 容器提供的工具获取该实例。您的具体问题是因为您手动使用 new
运算符创建类的实例而没有手动执行注入(inject)和后期构造调用,就像技术上正确但概念上错误示例如下:
authenticator = new UserAuthenticator();
authenticator.userRepository = new UserRepository();
authenticator.init();
换句话说,您错误地期望 new
运算符神奇地识别与 bean 管理和依赖注入(inject)相关的注释。
正确的方法取决于您要指出的负责创建和管理指定类实例的方法。如果它是 CDI,则只需告诉它使用 @Named @ApplicationScoped
在应用程序范围内仅创建一个支持 bean 类的托管 bean 实例。
import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;
@Named
@ApplicationScoped
public class UserAuthenticator {}
它只会被创建一次,并且可以通过 @Inject
在任何其他 Java EE 管理的工件中使用,如下所示(阅读:在任何其他用 @Named
注释的类中, @Stateless
, @ManagedBean
, @WebServlet
, @WebListener
, @WebFilter
, @Path
等):
@Inject
private UserAuthenticator userAuthenticator;
如果您绝对肯定需要一个静态方法来获取给定支持类的当前 CDI 托管 bean 实例,那么您应该通过 BeanManager
获取它,而不是手动构造实例(assuming Java EE 7 / CDI 1.1 available):
@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));
}
用法:
UserAuthenticator userAuthenticator = YourCDIUtil.getCurrentInstance(UserAuthenticator.class);
// ...
另见:
关于java - @Inject 和@PostConstruct 不能在单例模式下工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31098054/