Contexts and Dependency Injection for Java EE (CDI) 上下文和依赖注入是几个Java EE功能之一,有助于将Web层和Java EE平台的事务层编织在一起。 CDI是一组服务,一起使用,使开发人员可以轻松地在Web应用程序中使用企业bean以及JavaServer Faces技术。 CDI设计用于状态对象,还具有许多广泛的应用,允许开发人员以松散耦合但是类型安全的方式集成各种组件的灵活性非常大。
CDI 1.1由JSR 346指定。CDI使用的相关规范包括:
JSR 330,Java的依赖注入
Managed Bean规范是Java EE 7平台规范(JSR 342)的分支,
入门
上下文和依赖注入(CDI)使您的对象能够自动将其依赖性提供给它们,而不是创建它们或作为参数来接收它们。 CDI还管理这些依赖关系的生命周期。
例如,考虑以下servlet:
@WebServlet("/cdiservlet")
public class NewServlet extends HttpServlet {
private Message message;
@Override
public void init() {
message = new MessageB();
}
@Override
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException {
response.getWriter().write(message.get());
}
}
这个servlet需要一个实现Message接口的对象实例:
public interface Message {
public String get();
}
servlet创建自己一个以下对象的实例:
public class MessageB implements Message {
public MessageB() { }
@Override
public String get() {
return "message B";
}
}
使用CDI,此servlet可以声明其对Message实例的依赖,并由CDI运行时自动注入。 新的servlet代码如下:
@WebServlet("/cdiservlet")
public class NewServlet extends HttpServlet {
@Inject private Message message;
@Override
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException {
response.getWriter().write(message.get());
}
}
CDI运行时查找实现Message接口的类,找到MessageB类,创建一个新的实例,并在运行时将其注入到servlet中。 为了管理新实例的生命周期,CDI运行时需要知道实例的范围。 在这个例子中,servlet只需要实例来处理一个HTTP请求; 然后实例可以被垃圾回收。 这是使用javax.enterprise.context.RequestScoped注释指定的:
@RequestScoped
public class MessageB implements Message { ... }
MessageB类是一个CDI bean。 CDI bean是CDI可以自动实例化,管理和注入以满足其他对象的依赖关系的类。 几乎所有的Java类都可以被CDI管理和注入。
在这个例子中,MessageB是唯一实现Message接口的类。 如果应用程序具有多个接口实现,则CDI提供了可用于选择要注入哪个实现的机制。
CDI概述
CDI提供的最基本的服务如下。
上下文:此服务使您能够将有状态组件的生命周期和交互绑定到定义明确但可扩展的生命周期环境。
依赖注入:此服务使您能够以类型安全的方式将组件注入到应用程序中,并在部署时选择要注入的特定接口的实现。
此外,CDI还提供以下服务:
与表达式语言(EL)集成,允许任何组件直接在JavaServer Faces页面或JavaServer Pages页面中使用
- 装饰注入组件的能力
- 使用类型安全拦截器绑定将拦截器与组件相关联的能力
- 事件通知模型
- 除了由Java Servlet规范定义的三个标准范围(请求,会话和应用程序)之外的Web会话范围
- 完整的服务提供程序接口(SPI),允许第三方框架在Java EE 7环境中完美集成
CDI的主题是松耦合。 CDI执行以下操作:
- 通过定义良好的类型和限定符来解除服务器和客户端,从而使服务器实现可能会有所不同
- 解除合作组件的生命周期
- 使组件上下文,具有自动生命周期管理
- 允许有状态组件像服务一样进行交互,纯粹通过消息传递
- 通过事件将消息生产者完全消除消费者
- 通过Java EE拦截器解耦正交关系