CDI - @Injected 字段为空
CDI - @Injected field null
我想初始化一个集合并在我的应用程序启动时用数据填充它。然后我想在我的应用程序中的任何地方访问它。例如,我希望我的 REST API 可以访问已填充数据的共享集合。
我首先尝试使用带有@Startup 和@Singleton 注释的初创公司class 来做到这一点。当我在那里注入我的 userService 时,我遇到了一些问题,并且由于此 post 中的建议: 我尝试使用 @ApplicationScoped 注释来做到这一点:
@Named
@ApplicationScoped
public class KwetterApp {
@Inject
private UserService service;
@PostConstruct
public void init() {
try {
User harry = new User("Harry", "harry@outlook.com", "New York", "http://harry.com", "Hi, I'm Harry!", UserType.REGULAR);
User nick = new User("Nick", "nick@outlook.com", "California", "http://nick.com", "Hi, I'm Nick!", UserType.REGULAR);
User jane = new User("Jane", "jane@outlook.com", "Texas", "http://jane.com", "Hi, I'm Jane!", UserType.REGULAR);
Tweet tweet = new Tweet("eating...", harry);
Tweet tweet1 = new Tweet("swimming...", harry);
Tweet tweet2 = new Tweet("jogging...", jane);
harry.addTweet(tweet);
harry.addTweet(tweet1);
jane.addTweet(tweet2);
service.create(harry);
service.create(nick);
service.create(jane);
}
catch (Exception e){
e.printStackTrace();
}
}
public UserService getService() {
return service;
}
}
我在我的休息服务中注入这个class:
@RequestScoped
@Path("/user")
public class UserRest {
// @Inject
// private UserService userService;
@Inject
private KwetterApp kwetterApp;
// private KwetterApp kwetterApp = KwetterApp.getInstance();
private UserService userService = kwetterApp.getService();
@GET
@Produces({"application/json"})
public List<User> get() throws UserException {
return userService.getAll();
}
}
注入此 KwetterApp 时会导致以下异常:
StandardWrapperValve[rest.RestApplication]: Servlet.service() for servlet rest.RestApplication threw exception
java.lang.NullPointerException
at rest.UserRest.<init>(UserRest.java:27)
at rest.UserRest$Proxy$_$$_WeldClientProxy.<init>(Unknown Source)
我有一个空的 beans.xml 文件,bean-discovery-mode 设置为 'all'。 CDI 框架应该识别我的 KwetterApp class 进行注入,对吧?为什么为空?
提前致谢,
麦克
这里
@Inject
private KwetterApp kwetterApp;
private UserService userService = kwetterApp.getService();
我认为 kwetterApp
字段不会设置在 userService
之前。
CDI
将在构造对象后设置该字段。
无论如何都应该使用的替代方法是构造函数注入
@RequestScoped
@Path("/user")
public class UserRest {
private KwetterApp kwetterApp;
private UserService userService;
protected UserRest() {}
@Inject
public UserRest(final KwetterApp kwetterApp) {
this.kwetterApp = kwetterApp;
this.userService = kwetterApp.getService();
}
@GET
@Produces({"application/json"})
@Override
public List<User> get() throws UserException {
return userService.getAll();
}
}
需要 protected
构造函数,因为 @RequestScoped
是普通范围的 bean,并且它必须是可代理的,如规范中所述。
唯一不需要空构造函数的注释是 @Singleton
(来自 javax.inject
)。
如果你想使用注入的bean来初始化一个对象,那么你必须使用@PostConstruct注解的方法,因为注入的CDI bean只能在@PostContruct注解的方法中的CDI中使用,之后而不是在字段中初始化或构造函数调用。
因此,UserService 已经是一个 CDI bean,您可以将它注入到您的 rest 服务 bean 中,因为它将与当前活动范围内使用的 bean 相同。 KwetterApp 在当前活动范围内可用,因此 UserService 也将可用。只有 @Dependend 范围的 bean 表现不同,每个 bean 都有自己的实例。
我想初始化一个集合并在我的应用程序启动时用数据填充它。然后我想在我的应用程序中的任何地方访问它。例如,我希望我的 REST API 可以访问已填充数据的共享集合。
我首先尝试使用带有@Startup 和@Singleton 注释的初创公司class 来做到这一点。当我在那里注入我的 userService 时,我遇到了一些问题,并且由于此 post 中的建议:
@Named
@ApplicationScoped
public class KwetterApp {
@Inject
private UserService service;
@PostConstruct
public void init() {
try {
User harry = new User("Harry", "harry@outlook.com", "New York", "http://harry.com", "Hi, I'm Harry!", UserType.REGULAR);
User nick = new User("Nick", "nick@outlook.com", "California", "http://nick.com", "Hi, I'm Nick!", UserType.REGULAR);
User jane = new User("Jane", "jane@outlook.com", "Texas", "http://jane.com", "Hi, I'm Jane!", UserType.REGULAR);
Tweet tweet = new Tweet("eating...", harry);
Tweet tweet1 = new Tweet("swimming...", harry);
Tweet tweet2 = new Tweet("jogging...", jane);
harry.addTweet(tweet);
harry.addTweet(tweet1);
jane.addTweet(tweet2);
service.create(harry);
service.create(nick);
service.create(jane);
}
catch (Exception e){
e.printStackTrace();
}
}
public UserService getService() {
return service;
}
}
我在我的休息服务中注入这个class:
@RequestScoped
@Path("/user")
public class UserRest {
// @Inject
// private UserService userService;
@Inject
private KwetterApp kwetterApp;
// private KwetterApp kwetterApp = KwetterApp.getInstance();
private UserService userService = kwetterApp.getService();
@GET
@Produces({"application/json"})
public List<User> get() throws UserException {
return userService.getAll();
}
}
注入此 KwetterApp 时会导致以下异常:
StandardWrapperValve[rest.RestApplication]: Servlet.service() for servlet rest.RestApplication threw exception
java.lang.NullPointerException
at rest.UserRest.<init>(UserRest.java:27)
at rest.UserRest$Proxy$_$$_WeldClientProxy.<init>(Unknown Source)
我有一个空的 beans.xml 文件,bean-discovery-mode 设置为 'all'。 CDI 框架应该识别我的 KwetterApp class 进行注入,对吧?为什么为空?
提前致谢,
麦克
这里
@Inject
private KwetterApp kwetterApp;
private UserService userService = kwetterApp.getService();
我认为 kwetterApp
字段不会设置在 userService
之前。
CDI
将在构造对象后设置该字段。
无论如何都应该使用的替代方法是构造函数注入
@RequestScoped
@Path("/user")
public class UserRest {
private KwetterApp kwetterApp;
private UserService userService;
protected UserRest() {}
@Inject
public UserRest(final KwetterApp kwetterApp) {
this.kwetterApp = kwetterApp;
this.userService = kwetterApp.getService();
}
@GET
@Produces({"application/json"})
@Override
public List<User> get() throws UserException {
return userService.getAll();
}
}
需要 protected
构造函数,因为 @RequestScoped
是普通范围的 bean,并且它必须是可代理的,如规范中所述。
唯一不需要空构造函数的注释是 @Singleton
(来自 javax.inject
)。
如果你想使用注入的bean来初始化一个对象,那么你必须使用@PostConstruct注解的方法,因为注入的CDI bean只能在@PostContruct注解的方法中的CDI中使用,之后而不是在字段中初始化或构造函数调用。
因此,UserService 已经是一个 CDI bean,您可以将它注入到您的 rest 服务 bean 中,因为它将与当前活动范围内使用的 bean 相同。 KwetterApp 在当前活动范围内可用,因此 UserService 也将可用。只有 @Dependend 范围的 bean 表现不同,每个 bean 都有自己的实例。