所谓spring主动注入,是指容器中的一个组件中须要用到另一个组件(例如聚合关系)时,依附spring容器创建对象,而不是手动创立,次要有三种形式:

  1. @Autowired注解——由spring提供
  2. @Resource注解——由JSR-250提供
  3. @Inject注解——由JSR-330提供

@Autowired注解的应用办法

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Autowired {   /**    * Declares whether the annotated dependency is required.    * <p>Defaults to {@code true}.    */   boolean required() default true;}

从源码能够看出:该注解能够用在结构器、办法、参数、属性上,最常见的是用在属性上。
该注解只有一个属性: required,默认为true,如果找不到匹配的bean则报错;设置为false,如果找不到匹配的bean则注入null,并不会报错。
能够配合@Qualifier应用,用于精准指定要注入的bean的名称。
能够配合@Primary应用,当容器中存在多个雷同类型的组件时,用于指定优先加载哪一个,这个注解不能用在2个或更多同类型的组件上。

  1. 当容器中只有一个该类型的组件时
    |-不应用@Qualifier,会按bean类型查找,即applicationContext.getBean(bean.class),而后注入这个惟一的bean。
    |-应用@Qualifier,会按Qualifier的value值跟bean名称匹配查找,即applicationContext.getBean("Qualifier的value值")。
  2. 当容器中没有该类型的组件时
    |-required=true——报错expected at least 1 bean which qualifies as autowire candidate。
    |-required=false——注入null。
  3. 当容器中存在多个该类型的组件时
    |-不应用@Qualifier和@Primary时,会按属性名跟bean名称匹配查找,即applicationContext.getBean("属性名")。
    |-应用@Primary、但不应用@Qualifier时,会优先加载带有@Primary注解的组件。
    |-应用@Qualifier时,不论有没有应用@Primary,都会间接按Qualifier的value值跟bean名称匹配查找。
    综上,当容器中存在多个同类型的组件时,加载优先级:@Qulifier>@Primary>属性名,例如上面这个容器中蕴含3个BookDao组件
@Configuration@ComponentScan(basePackages = {"cn.monolog.service"})public class AutowiredBeanConfig {    @Bean(value = "bookDao1")    public BookDao bookDao1() {        BookDao bookDao = new BookDao();        bookDao.setLabel("bookDao1");        return bookDao;    }    @Bean(value = "bookDao2")    @Primary    public BookDao bookDao2() {        BookDao bookDao = new BookDao();        bookDao.setLabel("bookDao2");        return bookDao;    }    @Bean(value = "bookDao3")    public BookDao bookDao3() {        BookDao bookDao = new BookDao();        bookDao.setLabel("bookDao3");        return bookDao;    }}

主动注入形式是这样的:
@Autowired
@Qualifier(value = "bookDao1")
private BookDao bookDao3;
依照优先级程序,@Qulifier(bookDao1) > @Primary(bookDao2) > 属性名(bookDao3),最终加载的是名称为bookDao1的组件。

@Inject注解的应用办法
@Inject注解的应用办法跟@Autowired也根本类似,然而须要留神

  1. 应用前须要导入jar包——javax.inject;
  2. 反对@Primary注解,而且因为没有准确匹配,@Primary的优先级最高;
  3. 不反对required=false,即不能注入null,如果找不到组件必定报错;
  4. 默认依照类型匹配查找。

例如,上面这容器中有一个EmployeeDao组件

@Configurationpublic class InjectBeanConfig {    @Bean(value = "employeeDao1")    public EmployeeDao employeeDao1() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("1");        return employeeDao;    }}

主动注入的形式如下
@Inject
private EmployeeDao employeeDao3;

spring会先按属性名查找名称为employeDao3的组件,即applicationContext.getBean("employeeDao3"),后果不存在;
而后依照类型查找,即applicationContext.getBean(EmployeDao.class),找到employeDao1组件,胜利注入。
如果容器中有多个同类型组件,例如

@Configurationpublic class InjectBeanConfig {    @Bean(value = "employeeDao1")    public EmployeeDao employeeDao1() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("1");        return employeeDao;    }    @Bean(value = "employeeDao2")    public EmployeeDao employeeDao2() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("2");        return employeeDao;    }    @Bean(value = "employeeDao3")    public EmployeeDao employeeDao3() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("3");        return employeeDao;    }}

注入形式还是这样
@Inject
private EmployeeDao employeeDao3;
依然会按属性名和bean的名称匹配,即applicationContext.getBean("employeeDao3"),找到employee3,胜利注入。

然而如果其中某个组件加了@Primary注解,会疏忽属性名,优先注入,例如

@Configurationpublic class InjectBeanConfig {    @Bean(value = "employeeDao1")    public EmployeeDao employeeDao1() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("1");        return employeeDao;    }    @Bean(value = "employeeDao2")    @Primary    public EmployeeDao employeeDao2() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("2");        return employeeDao;    }    @Bean(value = "employeeDao3")    public EmployeeDao employeeDao3() {        EmployeeDao employeeDao = new EmployeeDao();        employeeDao.setLabel("3");        return employeeDao;    }}

无论注入时应用什么样的属性名,都会注入employeeDao2。

@Resource注解的应用办法
@Resource注解的应用跟@Autowired注解相似,然而须要留神:

  1. 不反对@Primary注解,也不反对reuqired=false,即不容许注入null;
  2. 该注解有一个属性name,相似于@Qualified精准匹配,优先级最高;
  3. 默认依照属性名跟bean的名称匹配查找,如果不存在,再按类型匹配查找。
    例如,上面这个容器中有两个CarDao组件
@Configuration@ComponentScan(basePackages = {"cn.monolog.service"})public class ResourceBeanConfig {    @Bean(value = "carDao1")    public CarDao carDao1() {        CarDao carDao = new CarDao();        carDao.setLabel("1");        return  carDao;    }    @Bean(value = "carDao2")    public CarDao carDao() {        CarDao carDao = new CarDao();        carDao.setLabel("2");        return  carDao;    }}

主动注入形式如下,会按属性名注入carDao2组件。
//主动注入
@Resource
private CarDao carDao2;
然而改为上面这种注入形式:
//主动注入
@Resource(name = "carDao1")
private CarDao carDao2;
因为应用了name精准匹配,会疏忽属性名,注入carDao1组件。