dau*_*ruy 5 java singleton dependency-injection java-ee postconstruct
我有一个课程如下:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我打电话的时候
UserAuthenticator authenticator = UserAuthenticator.getInstance();
Run Code Online (Sandbox Code Playgroud)
init() 方法未被调用,而userRepository是 null
我的Web应用程序在JBOSS EAP 6.3中运行.
这是怎么造成的,我该如何解决?
在Java EE应用程序中,不要单身思考.这只是麻烦和困惑的秘诀.相反,想想" 只创造一个 ".告诉Java EE容器只创建指定类的一个实例,应用程序范围,并通过Java EE容器提供的工具获取实例.您的具体问题是由于您使用运算符手动创建类的实例new而没有手动执行注入和post构造调用,如下面的技术正确但概念上错误的示例:
authenticator = new UserAuthenticator();
authenticator.userRepository = new UserRepository();
authenticator.init();
Run Code Online (Sandbox Code Playgroud)
换句话说,您错误地预期new操作员会神奇地识别bean管理和依赖注入相关的注释.
正确的方法取决于您要指出的负责创建和管理指定类的实例的方法.如果它是CDI,那么只需告诉它只使用应用程序范围创建支持bean类的一个托管bean实例@Named @ApplicationScoped.
import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;
@Named
@ApplicationScoped
public class UserAuthenticator {}
Run Code Online (Sandbox Code Playgroud)
将创建了一次,并通过提供@Inject任何其他Java EE管理神器如下(阅读:在注释的任何其他类@Named,@Stateless,@ManagedBean,@WebServlet,@WebListener,@WebFilter,@Path,等):
@Inject
private UserAuthenticator userAuthenticator;
Run Code Online (Sandbox Code Playgroud)
如果您非常肯定需要一个静态方法来获取给定支持类的当前CDI托管bean实例,那么您应该通过BeanManager以下方式获取它,而不是手动构造实例(假设Java EE 7/CDI 1.1可用)):
@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));
}
Run Code Online (Sandbox Code Playgroud)
用法:
UserAuthenticator userAuthenticator = YourCDIUtil.getCurrentInstance(UserAuthenticator.class);
// ...
Run Code Online (Sandbox Code Playgroud)