了解cdi Instance <>和.get()vs @Inject

Chr*_*ile 8 java-ee cdi java-ee-6 jboss-weld

我对以下情况中使用哪个有点困惑:

假设servlet创建一个处理用户http会话的Application,应用程序是这样的:

public class Application extends AbstractHTTPApplication {

@Inject
private Instance<MainView> mainView;

public void setupApplication() {
   this.setView( mainView.get() );
}
Run Code Online (Sandbox Code Playgroud)

后来我有一个@SessionScopedbean SSB,我想注入每个用户的bean:

@SessionScoped
public class SSB {}
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试使用常规@Inject SSB ssb;字段时MainView,我没有SSB为每个用户获取新内容:

public class MainView {

@Inject
private SSB usersSSB;

   public someMethod() {
       usersSSB.doSomething();
       System.identityHashCode( usersSSB );
   }
}
Run Code Online (Sandbox Code Playgroud)

在两个用户的测试中,我在两个用户的会话中得到了相同的实例usersSSB.我认为这不可能......我想,既然SSB是SessionScoped,每个用户会话都会有一个新的,无论它在哪里@Inject编辑,它都会引用用户的SSB.

相反,我试过:

public class MainView {

@Inject
private Instance<SSB> usersSSB;

   public someMethod() {
       usersSSB.get().doSomething();
       System.identityHashCode( usersSSB.get() );
   }
}
Run Code Online (Sandbox Code Playgroud)

现在它最终报告了usersSSB每个用户的不同.

这里发生了什么事?当我usersSSB.get()稍后在每个用户的会话中调用时,每次都会为同一个用户usersSSB.get()返回相同的bean吗?

我正在使用Glassfish 3.1.2.

更多信息

Application类正在新的HttpServletRequest上注入到Servlet中:

public abstract class AbstractCdiApplicationServlet extends
    AbstractApplicationServlet {
@Inject
protected Instance<ApplicationWrapper> wrapper;

@Override
protected Application getNewApplication(HttpServletRequest request)
        throws ServletException {
    return wrapper.get().getApplication();
}
...etc etc
Run Code Online (Sandbox Code Playgroud)

而且ApplicationWrapper是一个SessionScoped豆子:

@SuppressWarnings("serial")
@SessionScoped
public class ApplicationWrapper implements Serializable {
@Inject
private AbstractCdiApplication application;

public AbstractCdiApplication getApplication() {
    return application;
}
 }
Run Code Online (Sandbox Code Playgroud)

这是不是意味着@Inject SSB usersSSB在MainView(或该用户的会话中的任何对象)中的任何地方调用应该为每个用户的会话提供该用户的会话范围的bean,并且始终是相同的会话范围的bean?含义 - 针对不同用户的不同用户SSB,因为每个用户具有不同的会话.

毕竟,它Application本身是一个SessionScopedbean,通过getNewApplicationservlet 的方法注入并附加到用户的HTTP Session ?我的意思是,毕竟正是Application对象注入并附加了MainView类,对吧?这意味着MainView是一个会话范围的bean,不是吗?

我猜,我只想弄清楚这一切是如何运作的.谢谢您的帮助!

Krz*_*ksa 7

这是因为'@Inject Instance <>'是动态获得的,不像'@Inject'

如果你在ApplicationScoped bean中执行'@Inject',那么只能获得一次注入,因此在ApplicationScoped bean中对所有用户都是同一个引用

如果在'@Inject Instance <>'上调用.get(),则每次调用时都会动态获取对SSB的引用.get()

有关注射的更多信息,请参阅此处:http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/injection.html