JSR330 DI

JSR 330 ,提供了一种可重用的、可维护、可测试的方式来获取Java对象。也称为Dependency Injection 。

DI应该都不陌生,因为它就是Spring core之一。在Spring盛行后,Google也提供了一种DI实现:Guice。因为这两个DI容器的盛行,JSR在2009年时诞生了。随后Spring、Guice也相继支持了该规范。

DI容器,也称为Injector。可以有多种实现方式,可以基于XML、注解、DSL(Domain-specific language),甚至是Java代码。在实现是,可以采用反射、代码生成技术等等,均不受限制。

内容摘要:

javax.inject

下面就说说JSR 330 规范是如何定义的:

Interface Summary

Provider<T>

Provides instances of T.

Annotation Types Summary

Inject

Identifies injectable constructors, methods, and fields.

Named

String-based qualifier.

Qualifier

Identifies qualifier annotations.

Scope

Identifies scope annotations.

Singleton

Identifies a type that the injector only instantiates once.

@Inject

该注解可以在constructor、field、method上使用,也可以在static 的非 final 的field、method上使用。使用该注解标注的constructor、field、method访问修饰符不受限制,可以是private、package、protected、public中任意一种。Injector在进行注入时,要按照constructors、fiedls、methods的顺序进行。

对被标注的constructor的要求:

在满足上述说明的情况下,可以有其他的依赖作为方法的参数,别的要求倒没有什么。

对被标注的field的要求:

1)字段不能是final的。

对被标注的method的要求:

1)方法不能是abstract。

2)可以有其他的依赖作为方法的参数。

如果一个@Inject 的方法A.a,被子类B重写了方法a,但没有指定@Inject,那么就不会注入。

@Qualifier

它是一个元注解,用在标注一个注解的。被@Qualifier标注的注解,称为Qualifier。用于指定采用哪个实例。

譬如说,A类有两个子类A1,A2。B类依赖了A,那么DI容器在为B的实例注入A依赖时到底该注入哪个实例呢?

Class B{
    @Inject
    A a;
}

如果使用这个注解,就可以解决该问题了:

定义来个Qualifier注解:

@Qualifier
public @interface A_1 {
}

@Qualifier
public @interface A_2 {
}

然后对A1、A2两个类分别标注,加以区分:

@A_1
public class A1{
}

@A_2
public class A2{
}

如果你希望注入的是A1,那么Class B应该这样调整:

Class B{
    @Inject
    @A_1
     A a;
}

在JSR 330中,也默认设计了一个基于字符串命名的Qualifier,也就是@Named。

对上述案例,可以改造如下:

@Named(“A1”)
Public class A1{
}

@Named(“A2”)
Public class A2{
}

Class B{
    @Inject
    @Named(“A1”)
    A a;
}

也就是说,一个Qualifier可以把一个类定义成一个依赖类(类A1,A2中的使用方式),也可以用在注入时指定注入哪个依赖类的实例(Class B中的使用方式)。

@Named

它就是上面说的,默认的Qualifier。通过上面的例子,可以将其理解为Spring中的:

@Component:用于一个类上,告诉DI容器,这个类由DI容器来创建,并可以作为依赖类去注入到其他类中。

@Qualifier:用于指定使用哪个依赖类的实例。

上述代码在Spring中的写法是:

@Component(“A1”)
Class A1{
}

@Component(“A2”)
Class A2{
}

Class B{
    @Autowired
    @Qualifier(“A1”)
    A a;
}

@Scope、@Singleton

@Scope是Scope的元注解。用于声明Scope注解。譬如@Singleton。

Scope注解,用在类上,用于告诉Injector,为该类创建多少个对象。

也默认提供了一个Scope:@Singleton,它用于告诉容器,只为该类创建一个实例。所以当一类类被标注为@Singleton时,要注意线程安全性。

如果一个@Named或者其他自定义的Qualifier标准的类,没有被标注为@Singleton,那么就会创建多个实例。

单实例例子:

// Spring中的写法:
@Component(“cxxx”)
@Scope(“Singleton”)
public class C{
}

// 如果用JSR 330就可以写为:
@Named(“cxxx”)
@Scope(“prototype”)
public class C{
}

多实例例子:

// Spring中的写法:
@Component(“cxxx”)
public class C{
}

// 如果用JSR 330就可以写为:
@Named(“cxxx”)
public class C{
}

Provider

一个Provider用于提供某个类的实例。它就相当于Spring中的ObjectFactory。这是一个接口,不是一个注解,所以可以像其他的类一样使用它,它只有一个get方法。

class Car {
     @Inject Car(Provider<Seat> seatProvider) {
       Seat driver = seatProvider.get();
       Seat passenger = seatProvider.get();
       ...
     }
   }

我们也可以用它来解决类循环依赖的问题。

JSR330 vs Spring vs Guice vs HK2

功能说明

JSR330

Spring

Guice

HK2

告诉DI容器来管理一个类,并指定名称

@Named | Qualifier

@Component

   

告诉DI容器创建几个实例

@Singleton | 不写

@Scope(“Singleton”) | @Scope(“prototype”)

   

标注constructor、field、method是可住入的

@Inject

@Autowired

   

告诉DI容器注入哪个依赖

@Named | Qualifier

@Qualifier

   

自定义如何获取对象

Provider

ObjectFactory

   

此外,Spring、Guice、HK2 也已经支持JSR330了,所以你可以根据功能来选择使用JSR330的API。

JSR330: DI的更多相关文章

  1. Spring使用 --- 基本概念(一):DI,依赖注入

    Table of Contents 什么是依赖注入 怎样使用 什么时候使用 好处 本文讲述sprint基本概念之一: DI, 即依赖注入. 什么是依赖注入 说类A依赖于类B,最简单的例子是类A有一个类 ...

  2. 实战Asp.Net Core:DI生命周期

    title: 实战Asp.Net Core:DI生命周期 date: 2018-11-30 21:54:52 --- 1.前言 Asp.Net Core 默认支持 DI(依赖注入) 软件设计模式,那使 ...

  3. [PLC]ST语言六:DI/EI/FEND/WDT/FOR/NEXT

    一:DI/EI/FEND/WDT/FOR/NEXT 说明:简单的顺控指令不做其他说明. 控制要求:无 编程梯形图: 结构化编程ST语言:

  4. 核心一:DI

    1.DI:中文名称:依赖注入 2.英文名称:(Dependency Injection) 3.DI是什么?? 3.1 DI和IoC是一样的 3.2 当一个类(A)中需要依赖另一类(B)对象时,把B赋值 ...

  5. Spring学习(5):DI的配置

    一.  一些概念 应用程序中说的依赖一般指类之间的关系. 泛化:表示类与类之间的继承关系.接口与接口之间的继承关系: 实现:表示类对接口的实现: 依赖:当类与类之间有使用关系时就属于依赖关系,不同于关 ...

  6. spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入

    一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) ...

  7. Spring:DI依赖注入的几种方式

    据我所学,spring实现依赖注入(DI)的方式分为三大类:基于构造器(构造方法)的依赖注入.基于setter的依赖注入.其他方式(c命名空间.p命名空间等).其中推荐使用setter方法注入,这种注 ...

  8. Spring总结三:DI(依赖注入)

    简介: 所谓的依赖注入,其实是当一个bean实例引用到了另外一个bean实例时spring容器帮助我们创建依赖bean实例并注入(传递)到另一个bean中,比如你使用Spring容器创建的对象A里面需 ...

  9. 任务20:DI初始化的源码解读 & 任务21:依赖注入的使用

    20 我们来看一下asp.net core中依赖注入的源码 https://github.com/aspnet/AspNetCore/tree/master/src/Hosting 任务21:依赖注入 ...

随机推荐

  1. wpf中子窗口的几个问题

    今天研究了一下wpf中的窗口,写这篇文章来总结一下今天的收获.(转载请注明出处~) 总所周知,窗口是windows系统中十分重要的一个元素(从名字上就能体现出来),而一个应用程序总是包含很多窗口(主窗 ...

  2. 【原创】NuGet 出现“无法初始化 PowerShell 主机,如果将你的 PowerShell 执行策略设置设置为 AllSigned ,请先打开程序包管理控制台以初始化该主机” 错误的解决方法

    现象: 网上的设置 AllSigned 等方法都无效..后来考虑可能跟命令行版本兼容性有关系,然后在注册表命令行配置里发现一 ForceV2 设置项,抱着试一试的心态改了下,果然解决了! 解决方法:修 ...

  3. node.js 学习随笔

    一,cnmp的操作: 1,cnmp info jquery查询jquery的版本: 2,cnmp install jquery@1.11.1:安装: 3,cnmp list查询所有下载的内容: 4,c ...

  4. Java Web(五) JSP详解(四大作用域九大内置对象等)

    前面讲解了Servlet,了解了Servlet的继承结构,生命周期等,并且在其中的ServletConfig和ServletContext对象有了一些比较详细的了解,但是我们会发现在Servlet中编 ...

  5. Django实现用户注册登录

    学习Django中:试着着写一个用户注册登录系统,开始搞事情 =====O(∩_∩)O哈哈~===== ================= Ubuntu python 2.7.12 Django 1. ...

  6. 深入理解ajax系列第三篇——头部信息

    前面的话 每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用.XHR对象提供了操作头部信息的方法.本文将详细介绍HTTP的头部信息 默认信息 默认情况下,在发送XHR请求的同时,还会 ...

  7. c风格字符串,字符串字面值,c++字符串

    C风格字符串:本质上就是以空字符null为结束符的数组 可以简单的理解为:有'\0'的是c风格字符串,无'\0'的是普通字符数组 字符串字面值:是一串常量字符,字符串字面值常量用双引号括起来的零个或多 ...

  8. C#集合的应用以及和数组比较,它的好处有哪些

    我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类.我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和 ...

  9. oracle查看用户所占用的表空间

    select * from (select owner || '.' || tablespace_name name, sum(b) g from (select owner, t.segment_n ...

  10. 南京.NET技术行业落地分享交流会圆满成功

    3月11日,由南京.NET社区发起,纳龙科技赞助,并联合举办的,.NET技术线下交流活动,圆满成功. 这是南京.NET圈子第一次的小型聚会,为了办好此次活动,工作人员不敢怠慢.早早准备好了小奖品与水果 ...