繁体   English   中英

Servlet和CDI bean的作用域

[英]Servlets and scopes of CDI beans

tl; dr注入servlet的CDI bean怎么也可能在适当范围内?

在正式的oracle教程和一些书中,我们可以看到一些简单的示例,这些示例演示了如何将CDI bean注入servlet。 这非常简单,因为我们只需要使用@Inject批注并在beans.xml中启用bean发现。 我不了解的是,注入到servlet的@RequestScoped或@SessionScoped bean可能具有正确的范围。 servlet对象仅由容器创建一次,因此据我了解,注入也应该仅发生一次,或者应该发生某些意外行为。 但是当我们使用ie。 在bean类上的@RequestScoped注入是在对此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时,不会立即执行其post-construct方法。 您需要在Bean上执行一些方法才能触发post-cnstruct方法。

注入的不是请求范围的bean的实际实例。 实际上,它是动态生成的代理。 在该代理上调用方法(例如foo() )时,代理会在请求或会话范围内查找实际的bean实例,然后调用其foo()方法并将结果返回给Servlet。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM