CDI的概念理解

1、CDI是什么?目的和作用是什么?

        概念(是什么):是JavaEE 6标准中一个规范,

   作用(干什么): 它提供了Java EE平台上服务注入的组件管理核心,简化应该是CDI的目标,让一切都可以被注解被注入。 


和之前接触过的IOC/ID 有什么不同

(1)、将依赖注入IOC/DI上升到容器级别

(2)概念和我们之前在DCI架构中讨论的业务场景不一样,

包含有容器技术架构场景的意思,场景包括四种:

1、request (event),

2、session,
3、application,
4、page,
而SEAM框架拓展了两个 5、conversation 和 6、business process context 。 

简单的示例说明:  CDI对JSF和EJB模型使用都产生比较大的变化,比如对JSF影响,下面是JSF的一个用来显示的Bean:
 
import javax.inject.Named;

@Named
public class MessageServerBean {

    public String getMessage() {
        return "Hello World!";
    }
}

  

使用了@Named来标注
也就是说,@Named标注实际相当于给MessageServerBean取名eedemo.MessageServerBean(当然你也可以显式写一个名称),你就可以直接以messageServerBean对其getter方法进行输出了。
 
注释: 当然 eedemo.MessageServerBean 是一个默认的隐式名称 
 

Java EE CDI 主要使用@Inject注解来实现依赖注入,把受管理的bean注入到由容器管理的其它资源中去。

 

CDI还提供了@Decorator和@Interceptor,这涉及AOP和动态组件的概念。此处不做深入描述

@Named("itemProcessor")
@RequestScoped  //表示生命周期是request,每次request请求结束,生命就终止,也可以有Session或 Application等
public class ItemProcessor {

    @Inject
    private ItemDao itemDao; //表示ItemDao(业务类)需要被注入
  
//@ANY 修饰符
//为了提供完全松耦合的应用,我们通常把接口注入到受管理的资源中。
//当我们有多个实现了给定接口的bean时该怎么办呢?
//我们可以同时使用@Any修饰符和CDI的Instance接口,来把所有该接口的实现bean都注入进一个受管理的bean中:
@Inject 
      public void listServiceImplementations( 
          @Any Instance<Service> serviceList) { 
      
        for(Service service : serviceList){ 
          System.out.println(service.getClass().getCanonicalName()); 
        } 
      
      } 
    ...
}

  

@RequestScoped //表示生命周期是request,每次request请求结束,生命就终止,也可以有Session或 Application等
 

CDI这种事件模式还是组件(userEvent)驱动领域模型(user),不同于JF是领域模型自身发出事件,这两者还是有本质区别,更加突出领域模型作为业务核心的重要位置,而JavaEE6为了强调其技术架构的重要位置,免不了和业务争夺核心位置,这是我们使用者必须注意的,不能死读标准。

生产者方法的参数也可以经由CDI容器进行注入。请查看Java EE CDI Producer methods tutorial. 

 

CDI代理:

CDI创建代理是通过继承原来bean的类,并重写所有非私有方法。一个简单的典型的代理的例子可以像下面这样:

 

当一个Session范围的bean 被注入 application 范围作用域由于 application 范围内的 bean 是共享到整个项目中的  如果多个客户

同时访问这个 application里面被注入的这个 session 范围内的 bean 的话很有可能会造成  A用户访问的应该是 B用户 Session 范围bean 

的内容 、为了处理这种问题 CDI 创造了代理 并把代理注进注入点,由代理负责对应被注入的bean 的调用 

如下场景代码简单示例为: 

@SessionScoped 
    public class Service { 
      
      public void doWork() { 
        System.out.println("Working..."); 
      } 
      
    } 
      
      
// 在application范围内注入了 session范围内的bean 就造成了我上述的情况
    @ApplicationScoped  
    public class SomeBean { 
        
      @Inject 
      private Service service; // 这个注入是存在问题的
        
      public void test(){ 
        service.doWork(); 
      } 
      
  } 

  

CDI 代理 示例

//交给CDI进行代理 并重写所有service 非私有方法 然后以避免此问题发生
public class  Service$Proxy$_$$_WeldClientProxy  extends Service { 
    
      @Override 
      public void doWork() { 
        Service instance = // ... resolve bean instance 
        instance.doWork(); 
      } 
      
    } 

 

由于CDI代理通过继承bean的类来创建,所以当我们讨论非依赖性bean范围的时候,你应当明白CDI有如下一些限制

CDI 范围限制 请查看  :   javaEE CDI  bean scopes 

1、CDI不能注入原始类型

2、bean 必须有一个非私有的默认构造器

3、bean的类型不能用final 修饰  并且 bean中能有final 方法

 

 

 

 

 

posted @ 2019-07-27 18:33  不良徐某  阅读(1566)  评论(0编辑  收藏  举报