spring自动注入的三种方式

所谓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)
@Documented
public @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的组件。

@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组件。

@Inject注解的使用方法

@Inject注解的使用方法跟@Autowired也基本相似,但是需要注意

1. 使用前需要导入jar包——javax.inject;

2. 支持@Primary注解,而且因为没有精确匹配,@Primary的优先级最高;

2. 不支持required=false,即不能注入null,如果找不到组件肯定报错;

3. 默认按照属性名跟bean的名称匹配查找,如果不存在,再按类型匹配查找。

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

@Configuration
public 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组件,成功注入。

如果容器中有多个同类型组件,例如

@Configuration
public 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注解,会忽略属性名,优先注入,例如

@Configuration
public 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。

原文地址:https://www.cnblogs.com/dubhlinn/p/10708142.html

时间: 2024-10-31 19:09:40

spring自动注入的三种方式的相关文章

SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式

在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. Spring依赖注入(

Spring学习(二)spring ioc注入的三种方式

一.spring ioc注入有哪三种方式: a setter 原理 : 在目标对象中,定义需要注入的依赖对象对应的属性和setter方法:"让ioc容器调用该setter方法",将ioc容器实例化的依赖对象通过setter注入给目标对象,封装在目标对象的属性中. b 构造器 原理 : 为目标对象提供一个构造方法,在构造方法中添加一个依赖对象对应的参数.ioc容器解析时,实例化目标对象时会自动调用构造方法,ioc只需要为构造器中的参数进行赋值:将ioc实例化的依赖对象作为构造器的参数传入

【SSH三大框架】Spring基础第二篇:Spring依赖注入的三种方式

控制反转(Inversion of Control)和依赖注入(Dependency Injection): 应用控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它.也可以说,依赖被注入到对象中.所以,控制反转是,关于一个对象如何获取他所依赖的对象的引用,这个责任的反转. 对于依赖注入,有三种方式: 1.使用属性的setter方法注入 2.使用构造器注入 3.使用注解注入 下面我们介绍下这三种方式: 一.使用属性的setter方法注入 首先,我们写一个

Spring依赖注入的三种方式

Spring依赖注入(DI)的三种方式,分别为: 1. 接口注入 2. Setter方法注入 3. 构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个类: 接口 Logic.java 接口实现类 LogicImpl.java 一个处理类 LoginAction.java 还有一个测试类 TestMain.java Logic.java如下: package com.spring.test.di; public interface Logic { pub

Spring 使用AspectJ的三种方式

Spring 使用AspectJ 的三种方式 一,使用JavaConfig 二,使用注解隐式配置 三,使用XML 配置 背景知识: 注意 使用AspectJ 的 时候 要导入相应的Jar 包 嗯 昨天还碰到了这样的问题: Caused by: java.lang.IllegalArgumentEx http://pic.cnhubei.com/space.php?uid=1132&do=album&id=814854http://pic.cnhubei.com/space.php?uid=

【Spring】创建对象的三种方式

关于Spring的搭建可参见:浅析Spring框架的搭建.在测试之前还是应该先将环境配置好,将相关Jar包导进来.Spring创建的对象,默认情况下都是单例模式,除非通过scope指定. 一.通过构造函数创建对象. 2.1 利用无参构造函数+setter方法注入值 最基本的对象创建方式,只需要有一个无参构造函数(类中没有写任何的构造函数,默认就是有一个构造函数,如果写了任何一个构造函数,默认的无参构造函数就不会自动创建哦!!)和字段的setter方法. Person类: package com.

Web开发中获取Spring的ApplicationContext的三种方式

在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext 一       要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的.下面我们来跟踪一下源码 首先:从大家最熟悉的地方开始 Java代码   <listener> <

spring mvc handler的三种方式

springmvc.xml 三种方式不能针对一个controller同时使用 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="

Spring事务管理的三种方式

一 .第一种:全注解声明式事务 Xml代码 复制代码 收藏代码 1.<?xml version="1.0" encoding="UTF-8"?> 2.<beans xmlns="http://www.springframework.org/schema/beans" 3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4. xmlns:p=&quo