CDI Features inJavaEE 的上下文和依赖注入

基本的CDI的功能:

  • 类型安全:CDI使用Java类型来解析注入,而不是通过(字符串)名称注入对象。当类型不足时, 可以使用限定符 注释。这允许编译器轻松检测错误,并提供简单的重构。
  • POJO:几乎每个Java对象都可以由CDI注入!这包括EJB,JNDI资源,持久性单元和持久性上下文,以及之前由工厂方法创建的任何对象。
  • 可扩展性:每个CDI容器都可以通过使用便携式“扩展”来增强其功能。属性“portable”意味着无论哪个供应商,这些CDI Extensions都可以在每个CDI容器和Java EE 6服务器上运行。这是通过一个明确指定的SPI(服务提供者接口)实现的,该接口是JSR-299规范的一部
  • 分。
  • 拦截器:编写自己的拦截器从未如此简单。由于JSR-299的可移植性,它们现在也可以在每个经过EE 6认证的服务器和所有独立CDI容器上运行。
  • 装饰器:这些允许动态扩展现有的接口实现与业务方面。
  • 事件:CDI指定一种类型安全机制,用于发送和接收具有松散耦合的事件。
  • 统一EL集成:EL-2.2在灵活性和功能方面开辟了新的视野。CDI为它提供开箱即用的支持!

CDI的基本机制

依赖注入:DI有时被称为“好莱坞原则” - “不要打电话给我们,我们称之为你”。这意味着我们让容器管理实例的创建并注入它,而不是使用new运算符自己创建它们。当然,即使在DI容器中,没有任何人触发这个过程也没有任何反应。对于JSR-299容器,此触发器是对其中一个方法的调用。

T BeanManager#getReference(Bean<T> type, Qualifier... qualifiers);

返回给定类型T的实例。通过这样做,它不仅会 以递归方式创建返回的实例,还会创建所有@Inject-注释的子节点

通常, getReference(Bean <T>) 方法不是手动调用,而是由Expression Language Resolver在内部调用。写点东西

<h:inputText value="#{mailForm.text}"/>

ELResolver将查找名为“mailForm” 的Bean <T>并解析该实例。

范围,上下文,单例每个CDI容器的管理对象都是Ward Cunningham指定的原始意义上的“单例”,他不仅发明了Wiki,而且还与Kent Beck一起发明了1987年的计算机科学设计模式。

在这种意义上,“单身人士”意味着在指定良好的环境中只有一个实例。在Joshua Kerievsky对“重构模式”的评论中,Ward指出:

每个计算都有适当的上下文。面向对象编程的大部分内容都是关于建立上下文,关于平衡变量生命周期,使它们生活在合适的时间长度然后优雅地死亡。

CDI就是在一个明确的环境中创建单身人士。在我们的例子中,实例的生命周期由它们的范围定义。一个@ SessionScoped-注解豆每会话存在一次。

我们也可以将它命名为“会话单身人士”。如果用户 第一次访问我们的@SessionScoped bean,它将被创建并存储在会话中。每个后续访问都将返回完全相同的实例。会话结束时,存储在其中的所有CDI管理的实例也将被正确销毁。

 

如果我们有一个 @RequestScoped bean,我们可以称之为'request singleton',@ ConversationScoped bean是'conversation singleton'等。

Terminus'Managed Bean'

CDI规范中使用了一些术语,需要简短说明。Java中的术语“Bean”已经非常成熟,意味着带有getter和setter的POJO(Plain Old Java Object)。终端技术'Managed Bean'现在意味着完全不同的东西。它不是指类的实例,而是指可用于创建这些实例的元信息。它由接口 Bean <T>表示 ,将通过类路径扫描在容器启动时收集。

终点'上下文实例'

上下文实例正是我们每个范围的单例实例,我们的'会话单例','请求单例'等。通常用户从不直接使用上下文实例,而只是通过其'上下文参考'

终端'上下文引用'

默认情况下,CDI容器通过代理包装所有上下文实例,并仅注入代理而不是实例。在CDI规范中,这些代理称为“上下文引用”。CDI默认使用代理的原因有很多:

  • 序列化:我们只需序列化代理,而不是序列化整个对象。在反序列化时,它将再次自动“连接”到正确的上下文实例。
  • 范围差异:使用代理,可以将 @SessionScoped UserSettings 注入 @ApplicationScoped MailService, 因为代理将“连接”到正确的UserSettings本身。
  • 拦截器和装饰器:代理是以非侵入方式实现拦截器和装饰器的完美方式。

CDI容器的生命周期

让我们看一个简单的场景,在一个普通的Servlet引擎(如Apache Tomcat)中有一个CDI容器。如果WebApplication 启动, ServletFilter 将自动启动您的CDI容器,该容器将首先注册 ClassPath 上可用的所有CDI-Extensions ,然后从类扫描开始。 将扫描具有META-INF / beans.xml的所有ClassPath 条目, 并且将解析所有类并将其作为“Managed Bean”(接口Bean <T> )元信息存储在CDI容器内。在启动时扫描此信息的原因是:首先。及早发现错误,在运行时大大提高性能。

为了能够正确处理所有CDI作用域,CDI容器只使用标准的Servlet回调,如 ServletRequestListener HttpSessionListener

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-06-18 21:50  TangTaue  阅读(205)  评论(0编辑  收藏  举报