2KB项目,专业的源码交易网站 帮助 收藏 每日签到

Java EE CDI 依赖注入 (@Inject) 教程

  • 时间:2019-01-23 18:49 编辑:2KB 来源:2KB.COM 阅读:375
  • 扫一扫,手机访问
  • 分享
摘要: 英文原文:Jav
英文原文:Java EE CDI Dependency Injection (@Inject) tutorial

在本教程中,你将会学到几种不同的方法,用@Inject注解来实现Java EE CDI方式的依赖注入。

1. 简介

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

本教程基于如下环境:

  1. JDK 1.7.0.21
  2. Weld 1.1.10

Weld 是CDI 的参考实现。

2. 构造器依赖注入

public class SomeBean {
  
  private final Service service;

  @Inject
  public SomeBean(Service service){
    this.service = service;
  }

}

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

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

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

3. 字段依赖注入

public class SomeBean {
  
  @Inject
  private Service service;

}

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

4. 初始化方法依赖注入

public class SomeBean {
  
  private Service service;
  
  @Inject
  public void setService(Service service) {
    this.service = service;
  }

}

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

5.  @Any 修饰符

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

The @Any qualifier
public class SomeBean {
  
  @Inject
  public void listServiceImplementations(
      @Any Instance<Service> serviceList) {

    for(Service service : serviceList){
      System.out.println(service.getClass().getCanonicalName());
    }

  }
}

@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
@SessionScoped
public class Service {

  public void doWork() {
    System.out.println("Working...");
  }

}


@ApplicationScoped
public class SomeBean {
  
  @Inject
  private Service service;
  
  public void test(){
    service.doWork();
  }

}

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

其它翻译版本 (1) 加载中

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

CDI 代理 示例
public class Service$Proxy$_$$_WeldClientProxy 
  extends Service {

  @Override
  public void doWork() {
    Service instance = // ... resolve bean instance
    instance.doWork();
  }

}

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

  1. CDI 不能注入原始类型
  2. bean的类必须有一个非私有的默认构造器
  3. bean的类不能是final类型的并且不能有任何final方法
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部