当前位置: 首页 > 知识库问答 >
问题:

CDI bean的Servlet和范围

桓嘉谊
2023-03-14

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

在oracle官方教程和一些书籍中,我们可以看到一些简单的示例,展示如何将CDIBean注入servlet。这非常简单,因为我们只需要使用@Inject注释并在bean中启用bean发现。xml。我不明白的是,注入servlet的@RequestScoped或@SessionScoped bean的作用域是否正确。servlet对象只由容器创建一次,据我所知,注入也应该只发生一次,或者发生一些意外行为。但是,当我们在html" target="_blank">bean类上使用ie.@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();
    }
}

结果后发送3个请求 /beanURL我们可以看到,每次我们得到不同的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

共有2个答案

毋宪
2023-03-14

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

花阳秋
2023-03-14

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

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

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

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

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

 类似资料:
  • 我想注入CDI SessionScoped bean到JSP页面。 当我以这种方式使用bean时,它工作得很好,我在JSP页面上看到了初始值。 当我将同一个bean注入到一个服务中时就会出现问题,我从API中的另一个servlet调用该服务。在这种情况下,我不会在JSP页面上获得更新的值。看起来我使用注释在JSP页面和服务内部得到了不同的bean 有人能告诉我们如何在JSP和从servlet访问的

  • 看完这些,, 在哪里使用EJB3.1和CDI 下面的事情我还不明白,如果我错了,请纠正我。 与bean在同一个包中的所有类。xml是CDIBean,除了注释为session/message/singleton的类之外 非常感谢。:)

  • 问题内容: Jboss 4.2.3支持什么Servlet Spec和JSP版本? 问题答案: 这取决于它使用的Tomcat版本。根据规范/发行说明,它使用的是Tomcat6.0.x。因此,它支持Servlet 2.5 / JSP 2.1。

  • 是否可以在使用关键字创建的类中获取CDIBean的实例?我们目前正在对一个旧的应用程序进行一些增强,每次我们在应用程序中对CDI单例bean进行编程查找时,都会得到一个ContextNotActiveException。 获取参考的代码: BeanManager支持。JAVA

  • 本书是《Java Servlet 3.1 规范》的中文翻译,同时提供了大量 Servlet 3.1 实例,帮助你快速理解 Servlet 3.1 规范。至今为止,Servlet 3.1 是最新的正式版本,Servlet 4.0 仍在草案阶段。

  • 我有点困惑,我们将CDIBean称为我们使用注释注入它们的bean,还是我们在它们内部使用注入的bean?