我需要在Servlet中修改用户会话对象(SessionScoped bean-CDI),所以我必须以某种方式获取该bean。我用以下方式注射:
@Inject
private UserSession user;
其中UserSession是SessionScoped CDI bean。从doPost或doGet servlet方法调用 user 方法。 这很完美;每次@Inject注释都会注入相应的UserSession bean,但我不明白如何这种行为。
我假设使用@Inject注释的bean只注入一次(当创建对象 - 本例中的Servlet实例时),但这显然是错误的假设。
那么,这些bean什么时候注入到servlet中?按要求?当有多个UserSession对象时,这种方法如何避免冲突(一个servlet实例 - 处理它的多个线程)?
答案 0 :(得分:6)
CDI使用proxy pattern。注入的实例实际上不是真实实例,而是根据当前上下文定位实例的代理,并将所有方法委托给它(就像EJB的工作方式一样)。 UserSession
bean的自动生成类看起来大致如下:
public UserSessionCDIProxy extends UserSession implements Serializable {
public String getSomeProperty() {
UserSession instance = CDI.resolveItSomehow();
return instance.getSomeProperty();
}
public void setSomeProperty(String someProperty) {
UserSession instance = CDI.resolveItSomehow();
instance.setSomeProperty(someProperty);
}
}
此机制允许您在更广范围的实例中注入更窄范围的实例,并允许您仍然在当前上下文中获取预期实例。标准JSF @ManagedProperty
注释不支持它,仅仅因为它不使用代理,而是直接注入所需的实例。这就是为什么不可能通过@ManagedProperty
注入更窄范围的东西。
答案 1 :(得分:4)
你的答案在于CDI的C,代表上下文。
发生的事情不是注入实际的bean,而是代理。此代理是上下文的,并根据代表执行代理的调用方的上下文解析为实际的会话范围bean。