首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CDI的Servlets和作用域

CDI的Servlets和作用域
EN

Stack Overflow用户
提问于 2015-10-20 21:45:25
回答 2查看 2.2K关注 0票数 2

tl;dr :如何可能将CDI注入servlet也在适当的范围内?

在正式的oracle教程和一些书籍中,我们可以看到一些简单的示例,这些示例演示了如何将CDI注入servlet。这非常简单,因为我们只需使用@Inject注释并在beans.xml中启用bean发现。我不明白的是,如何使注入servlet的@RequestScoped或@SessionScoped bean具有正确的作用域。servlet对象只由容器创建一次,因此据我所知,注入也应该只发生一次或发生一些意想不到的行为。但当我们用ie。@RequestScoped在bean类上,注入发生在对这个servlet的每个请求之后(非常棒)。问题是它是如何深入运作的?

简单例子

代码语言:javascript
复制
public interface BeanInterface {
    public void beanInfo();
}

-

代码语言:javascript
复制
@RequestScoped
public class BeanImpl implements BeanInterface {
    @Override
    public void beanInfo() {
        System.out.println(this);
    }
}

-

代码语言:javascript
复制
@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个请求后,我们可以看到每次向单个servlet注入不同的bean。

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-20 22:06:11

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

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

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

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

代理还负责初始化bean,因此您可以观察到,@PostConstruct方法只有在必要时才会被延迟和执行--当代理上的方法被调用时。换句话说,当注入CDI时,它的后期构造方法不会立即执行。您需要在bean上执行一些方法,以便触发方法。

票数 6
EN

Stack Overflow用户

发布于 2015-10-20 21:55:38

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33247364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档