CDI-@Injected字段为空

时间:2019-03-13 14:39:55

标签: java cdi

我想初始化一个集合,并在应用程序启动时用数据填充它。然后,我想在应用程序中的任何地方访问它。例如,我想让我的REST API可以访问已经用数据填充的共享集合。

我首先尝试使用带有@Startup和@Singleton注释的启动类来完成此操作。当我将userService注入其中时,由于这篇文章中的建议,我遇到了一些问题:@Inject and @PostConstruct not working in singleton pattern我尝试使用@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;
    }
}

我将此类添加到我的休息服务中

@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)

我有一个空的bean.xml文件,其bean-discovery-mode设置为'all'。 CDI框架应该识别我的KwetterApp类用于注入,对吗?为什么它为空?

谢谢,

迈克

2 个答案:

答案 0 :(得分:1)

这里

cf.example.com/log_in

我认为@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是普通作用域的bean,并且必须是可替代的,如规范中所述。

唯一不需要空构造函数的注释是@RequestScoped(来自@Singleton)。

答案 1 :(得分:0)

如果要使用注入的Bean初始化对象,则必须使用@PostConstruct注释的方法,因为注入的CDI Bean仅在@PostContruct注释的方法中以及之后的CDI中可用,而在字段初始化或构造函数调用。

因此,UserService已经是一个CDI bean,您可以将其注入到您的rest服务bean中,因为它将与当前活动范围内使用的bean相同。 KwetterApp在当前活动范围内可用,因此UserService也将可用。只有@Dependend范围内的bean的行为不同,因此每个bean都提供了自己的实例。