所谓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。

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

  1. Spring静态注入的三种方式

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/chen1403876161/article/details/53644024Spring静态注入的三 ...

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

           于java发育.一类程序猿必须依靠类的其他方法,它是通常new依赖类的方法,然后调用类的实例,这样的发展问题new良好的班统一管理的例子.spring提出了依赖注入的思想,即依赖类不由程 ...

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

           在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依 ...

  4. Spring依赖注入的三种方式

    看过几篇关于Spring依赖注入的文章,自己简单总结了一下,大概有三种方式: 1.自动装配 通过配置applicationContext.xml中的标签的default-autowire属性,或者标签 ...

  5. Spring自动注入的几种方式

    ---恢复内容开始---   @Service("accountEmailService")public class AccountEmailServiceImpl impleme ...

  6. Spring基础05——Spring依赖注入的三种方式

    Spring支持3种依赖注入的方式:属性注入.构造器注入.工厂 1.属性注入 属性注入即通过setter方法注入Bean的属性或依赖的对象.使用<property>元素,使用name属性指 ...

  7. spring——依赖注入的三种方式

    1 构造器注入(与构造器有直接关系) 默认无参构造 3种构造方式:通过<contructor-arg>调用类中的构造器 下标 <bean id="userService&q ...

  8. Spring——自动装配的三种实现方式

    依赖注入的本质是装配,装配是依赖注入的具体行为 spring会在上下文中自动寻找,并自动给bean装配属性 自动装配的三种方式 (1).在xml中显式的装配 (2).在java中显式的装配 (3).隐 ...

  9. spring生成EntityManagerFactory的三种方式

    spring生成EntityManagerFactory的三种方式 1.LocalEntityManagerFactoryBean只是简单环境中使用.它使用JPA PersistenceProvide ...

随机推荐

  1. go & cron

    https://github.com/robfig/cron - 源码 cron - GoDoc 参考 go---定时任务 cron,gin 静态文件 go语言里比较好用的计划任务调度模块

  2. linux中文件权限格式与chmod命令以及用户和用户组的管理

    简单了解一下linux中的文件权限格式与chmod命令 chmod命令:改变文件或者目录的权限 格式:chmod [参数] [<权限范围><符号><权限代码>] - ...

  3. 前端校招知识体系之HTML5

    啥是HTML5?官方说HTML5 是下一代的 HTML... 本文主要介绍HTML5三个方面的知识,继续往下看看吧. 语义化标签 canvas&svg 响应式meta 一.语义化标签 语义化标 ...

  4. python中的面向对象和面向过程

    一.面向对象和面向过程 一.什么是面向过程 核心是过程二字:面向过程是一种流水线的工作流程,是先做什么在做什么 二.什么是面向对象 核心 是对象二字:是一种编程思想,上帝思维,一切皆对象,编程中负责调 ...

  5. 电子邮件协议:SMTP、POP3、IMAP4

    常见的电子邮件协议:SMTP.POP3.IMAP4   邮件发送协议:SMTP协议 邮件读取协议:POP3.IMAP4协议   SMTP协议(simple mail transfer protocol ...

  6. Apache 配置IP站点

    配置临时生效 IP: [root@Nagios-Server extra]# ifconfigeth0:0 192.168.1.126/24 up [root@Nagios-Server extra] ...

  7. dockerfile制作笔记

    dockerfile语法格式:   FROM: 基础镜像(就是在什么镜像上面做)   MAINTAINER: 镜像创建者信息(作者的信息)   EXPOSE: 开放的端口   ENV: 设置变量   ...

  8. spring,配置文件applictionContext.xml,Mybatis mybatis.xml,springMVC spring整合springMVC mybatis

  9. 跳转控制语句return

    return语句的作用不是为了跳出循环,更常用的功能是结束一个方法,也就是退出一个方法,跳转到上层调用的方法处. 演示案例: 结束循环其实是结束了main方法 public static void m ...

  10. Golang在京东列表页实践总结

    Golang在京东列表页实践总结 作者:张洪涛 10余年软件开发和设计经验,曾就职于搜狐.搜狗.前matrixjoy公司联合创始人.甘普科技CTO. 目前线上状态 基于搜索实现: 全量数据,搜索结果不 ...