概述
定义:Contextual Dependency Injection,上下文依赖注入。
context,上下文,可以绑定生命周期,可以与有状态的组件交互。
DI,依赖注入,以类型安全的方式注入一个组件到应用中去,包括指定特定实现注入。
CDI还提供了以下的服务:
集成EL语言,允许组件直接在JSF和JSP中使用。
可以修饰注入的组件。
能够使用类型安全的拦截器去和组件关联
一个事件通知模型
提供的作用域有:request,session,qpplication,conversation
有完整的SPI(Service Provider Interface),允许第三方集成
(CDI提供的服务这里只讲一些常见和常用到的,其他一下用法可以参考CDI官方文档)
为什么用CDI
CDI主要是为了解耦,之前我们需要在一个类中new另外一个类,代码耦合度很高,比如:
public class Student {
Teacher teacher = new Teacher();
}
当我们用了CDI之后,可以这样写:
public class Student {
@Inject
Teacher teacher;
}
这样我们就把new的这个动作交给容器了,并且使容器自动管理bean的生命周期,实现了component之间的松耦合
想要实现CDI管理的bean,需要满足下列全部条件(这里不包括JSF组件):
如果是内部类的话,只能是静态内部类
是一个具体的类或是被@Decorator修饰
没有被EJB的注解标注或不是ejb-jar.xml中的EJB bean
合适的构造器,下列条件其中之一:
无参构造器
用@Inject定义的一个构造器
可以注入的bean有哪些
几乎是任何一个Java类
Session beans
Java EE的资源:数据源,JMS,Queue,连接工厂
持久化上下文(JPA,EntityManager Objects)
生产者属性
返回生产值方法的实体
web service引用
远程企业级bean的引用
如何使用CDI
上面提到的那种是常见的
1
当一个接口,有多个实现类时,怎么让容器知道注入哪一个呢?
- 一个是用@Named直接指定类的名字,官方不推荐,这里不作展示
- 一个是用@Qualifier的方式,请看代码:
IStudent的写法:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface IStudent {
}
然后Student实现Person接口
然后由在另外一个需要用到的类里注入
@Inject
@IStudent
private Person student;
CDI应用的配置
CDI必须有beans.xml,文件可以为空,但必须有。
- 对一个web应用,这个文件必须在WEB-INF中。
- 对EJB模块或JAR文件,必须在META-INF下。