2012-03-26 60 views
7

我有点困惑,其在下列情况下使用:了解CDI实例<>和获得()VS @Inject

假设servlet创建处理用户的HTTP会话的应用,以及应用程序是这样的:

public class Application extends AbstractHTTPApplication { 

@Inject 
private Instance<MainView> mainView; 

public void setupApplication() { 
    this.setView(mainView.get()); 
} 

后来我有一个@SessionScopedSSB,我想注入到每个用户的Bean:

@SessionScoped 
public class SSB {} 

现在当我在MainView尝试了常规@Inject SSB ssb;作为一个领域,我不为每个用户得到一个新的SSB

public class MainView { 

@Inject 
private SSB usersSSB; 

    public someMethod() { 
     usersSSB.doSomething(); 
     System.identityHashCode(usersSSB); 
    } 
} 

测试有两个用户,我得到了这两个用户的会话usersSSB相同实例。我不认为这是可能的...我想,既然是SSB SessionScoped,一个新的将给予每个用户会话,不管它是@Inject编将参考用户SSB

相反,我想:

public class MainView { 

@Inject 
private Instance<SSB> usersSSB; 

    public someMethod() { 
     usersSSB.get().doSomething(); 
     System.identityHashCode(usersSSB.get()); 
    } 
} 

现在它报告为每个用户不同的usersSSB,终于。

这里发生了什么?当我后来打电话usersSSB.get()在每个用户的会话,将在usersSSB.get()回报同样豆每次同样用户?

我Glassfish上运行3.1.2。

一些更多的信息

的应用类被注入到Servlet的一个新的HttpServletRequest:

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 

而且ApplicationWrapperSessionScoped豆:

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

public AbstractCdiApplication getApplication() { 
    return application; 
} 
} 

隐而不宣“T这意味着调用@Inject SSB usersSSB随时随地的MainView(或任何该用户的会话中对象)应该给我说,用户的会话作用域的bean,并始终会话范围的bean,为每个用户的会话?含义 - 针对不同用户的不同用户SSB,因为每个用户都有不同的会话。

毕竟,Application本身是一个SessionScoped bean,通过servlet的getNewApplication方法注入并附加到用户的HTTP Session中?我的意思是,应用程序对象注入并连接MainView类毕竟是正确的?这意味着MainView是一个会话范围的bean,不是吗?

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

+0

这很奇怪。你有这个样本可用于测试吗? – LightGuard 2012-03-27 16:48:25

+0

老实说,我没有一个足够牢固的句柄来做一个简单的测试用例......是否有一个工作的maven原型可以用一个http servlet为你启动,为每个新会话创建一个应用程序?我可以用它来构建一个测试项目并发布它。 – 2012-03-28 21:38:59

回答

5

这会发生,因为“@注入实例<>”是动态的,不像来获得“@Inject”

如果你做“@注入”到ApplicationScoped豆则只能获得一次注射所以在ApplicationScoped豆将是这个每次动态获得对“@注入实例<>”所有用户

如果调用获得(),然后参照SSB相同的附图当调用获得()

更多关于注射可以读这里:http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/injection.html

+0

我在你的评论Krzusztof上添加了一些更多的信息。不应该将@Inject注入到SessionScoped bean(MainView)中,并且始终向该用户提供相同的对象?而且@ @ Inject应该给不同的用户一个*不同的*对象,因为他们在不同的会话中? – 2012-03-28 21:57:42

+1

你实际得到的是一个代理,每次都会查找正确的资源。 – LightGuard 2012-03-29 14:00:35

+1

不应该@Inject也给正确的资源代理? – 2012-03-29 14:09:27