Servlet和CDI bean的范围

tl; dr注入servlet的CDI bean如何也可能处于适当的范围内?

在官方的oracle教程和一些书中,我们可以看到简单的例子,展示了如何将CDI bean注入到servlet。 这很简单,因为我们只需使用@Inject注释并在beans.xml中启用bean发现。 我不明白的是,注入到servlet中的@RequestScoped或@SessionScoped bean具有合适的范围。 servlet对象只由容器创建一次,所以据我了解注入应该只发生一次,否则会出现一些意外的行为。 但是当我们使用ie时。 @RequestScoped对bean类的注入发生在对这个servlet的每个请求之后(好极了)。 问题在于它如何深入工作?

简单的例子

public interface BeanInterface {
    public void beanInfo();
}

-

@RequestScoped
public class BeanImpl implements BeanInterface {
    @Override
    public void beanInfo() {
        System.out.println(this);
    }
}

-

@WebServlet("/bean")
public class BeanServlet extends HttpServlet {
    //how is it injected with every GET/POST/... request
    @Inject
    private BeanInterface bean;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(this);
        bean.beanInfo();
    }
}

在向/ bean URL发送3个请求之后的结果,我们可以看到每次我们将不同的bean注入到单个servlet时。

23:35:18,062 INFO  [stdout] (default task-3) com.test.BeanServlet@1f2521b7
23:35:18,071 INFO  [stdout] (default task-3) com.test.BeanImpl@4a49ab25

23:35:23,883 INFO  [stdout] (default task-4) com.test.BeanServlet@1f2521b7
23:35:23,887 INFO  [stdout] (default task-4) com.test.BeanImpl@6ff1609e

23:35:27,286 INFO  [stdout] (default task-5) com.test.BeanServlet@1f2521b7
23:35:27,288 INFO  [stdout] (default task-5) com.test.BeanImpl@1edc9ec

注入的bean保留它们的作用域,因为真正注入servlet的是代理而不是真正的bean。

代理由CDI容器动态创建,并从注入的类或接口派生。 对于类,创建一个动态子类,为接口创建动态代理。

代理负责解析当前上下文,并决定是创建新的bean还是重用现有的bean。 然后,所有在注入代理上调用的方法都被转发到底层创建的或重用的bean。

您甚至可以将注入的代理传递给另一个bean或普通对象,并且将正确解析上下文,并调用正确的bean方法。 这是有效的,因为线程始终只有一个请求上下文,并且在任何时候,代理都可以访问其线程,并可以找出将哪个请求上下文分配给该线程。

代理还负责初始化bean,因此您可能会观察到,@ @PostConstruct方法被延迟并且仅在需要时才执行 - 当调用代理上的方法时。 换句话说,当注入CDI bean时,其后构建方法不会立即执行。 你需要在bean上执行一些方法来触发post-cnstruct方法。


注入的内容不是请求范围bean的实际实例。 它实际上是一个动态生成的代理。 在代理上调用一个方法(例如foo() )时,代理会在请求或会话作用域中查找实际的bean实例,调用它的foo()方法并将结果返回给servlet。

链接地址: http://www.djcxy.com/p/62215.html

上一篇: Servlets and scopes of CDI beans

下一篇: Inconsistent deployment of JSF ViewScoped CDI Bean accross two GF Servers