Java EE CDI依赖注入教程
yqxbc 发布时间:04-06 来源:一起学编程 浏览:14次

 1、简介

  Java EE CDI 主要使用@Inject注解来实现依赖注入,把受管理的bean注入到由容器管理的其它资源中去。在本教程中,我们将会介绍在CDI环境下几种不同的可选策略来实现依赖注入。

  本教程基于如下环境:

  1)JDK 1.7.0.21

  2)Weld 1.1.10

  Weld 是CDI 的参考实现。

  2、构造器依赖注入

 

  1. public class SomeBean { 
  2.         
  3.       private final Service service; 
  4.       
  5.       @Inject 
  6.       public SomeBean(Service service){ 
  7.         this.service = service; 
  8.       } 
  9.       
  10.     }

 

  当CDI容器在初始化一个SomeBean类型的bean实例时,它将会查找该类的默认构造器(无参构造器)并用它来创建bean实例。但是有一个例外情况,就是当我们还有一个使用@Inject 进行了注解的构造器时,这种情况下,容器会改用有注解的构造器而不是无参构造器,并且把通过构造器参数传入的依赖资源注入到bean实例中来。

  注意:记住一个类只允许有 一个@Inject注解的构造器。

  在上面的例子中,容器将会获取到一个Service 的实例并把它注入到SomeBean 的注解构造器中。

  3、字段依赖注入

 

  1. public class SomeBean { 
  2.         
  3.       @Inject 
  4.       private Service service; 
  5.       
  6.     }

 

  这种情况下,当容器初始化一个 SomeBean类型的bean时,它会把一个正确的Service实例注入给该字段,即使该字段是一个私有字段,并且不需要有任何setter方法。

  4、初始化方法依赖注入

 

  1. public class SomeBean { 
  2.         
  3.       private Service service; 
  4.         
  5.       @Inject 
  6.       public void setService(Service service) { 
  7.         this.service = service; 
  8.       } 
  9.       
  10.     }

 

  这种情况下,当容器初始化一个 SomeBean类型的bean时,它会调用所有由@Inject注解了的方法,并且通过方法参数的方式把依赖注入进来。

  5、@Any 修饰符

  为了提供完全松耦合的应用,我们通常把接口注入到受管理的资源中。当我们有多个实现了给定接口的bean时该怎么办呢?我们可以同时使用@Any修饰符和CDI的Instance接口,来把所有该接口的实现bean都注入进一个受管理的bean中:

  The @Any qualifier

 

  1. public class SomeBean { 
  2.         
  3.       @Inject 
  4.       public void listServiceImplementations( 
  5.           @Any Instance<Service> serviceList) { 
  6.       
  7.         for(Service service : serviceList){ 
  8.           System.out.println(service.getClass().getCanonicalName()); 
  9.         } 
  10.       
  11.       } 
  12.     }

 

  @Any 修饰符告诉容器,任何可供使用的依赖都适用于该注入点,所以容器会把他们都注入进来。 如果我们有接口的多个实现而我们只注入其中的一个 - 并且没有做任何排除工作 - 那么容器将会抱怨并且无法成功的初始化组件。我们将会在其他教程中介绍依赖排除问题。

  6、注入到生产者方法中

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

 7、CDI 代理

  如果我们不涉及CDI代理机制,那么本教程将是不完整的。当我们把一个在不同于@Dependent范围下创建出来的bean注入到另外一个托管资源时,CDI容器不会注入一个被注入bean的直接引用。

  CDI 中bean 的范围请看 Java EE CDI bean scopes

  为什么CDI使用代理? 因为如果bean的直接引用被注入,将会给被管理的bean造成诸如线程安全或并发访问的问题。

  设想一下一个Session 范围的 bean被注入到一个Application范围的bean中去的情形。由于application 范围的bean在所有客户端间共享,如果多个客户端同时访问一个application 范围的bean,那么将会存在很高的风险出现这种情况:一个客户端访问了其他客户端正在访问的session范围的bean。

  为了处理这种问题,CDI创造了代理并把代理注入进注入点。由代理负责处理对被注入bean的调用,并实际去调用正确的bean实例。

  CDI创建的代理继承自被注入bean的类型。设想一下下面的情形:

  Application 和  Session 范围的 bean

 

 

  1. @SessionScoped 
  2.     public class Service { 
  3.       
  4.       public void doWork() { 
  5.         System.out.println("Working..."); 
  6.       } 
  7.       
  8.     } 
  9.       
  10.       
  11.     @ApplicationScoped 
  12.     public class SomeBean { 
  13.         
  14.       @Inject 
  15.       private Service service; 
  16.         
  17.       public void test(){ 
  18.         service.doWork(); 
  19.       } 
  20.       
  21.   }

 

 

  CDI将把一个session范围的bean的代理注入进一个application范围的bean中去。每一次对session范围bean的调用,都 将通过代理进行,代理会把调用重定向到正确的session范围bean的实例,那个从属于正确的HTTP request session的bean。

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

  CDI 代理 示例

 

 

  1. ublic class Service$Proxy$_$$_WeldClientProxy 
  2.       extends Service { 
  3.       
  4.       @Override 
  5.       public void doWork() { 
  6.         Service instance = // ... resolve bean instance 
  7.         instance.doWork(); 
  8.       } 
  9.       
  10.     }

 

 

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

  1)CDI 不能注入原始类型

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

  3)bean的类不能是final类型的并且不能有任何final方法

如果你有好的win10资讯或者win10教程,以及win10相关的问题想要获得win10系统下载的关注与报道。
欢迎加入发送邮件到657025171#qq.com(#替换为@)。期待你的好消息!