Spring 中的自动装配
目录
- 1. 前言
- 1.1 Spring 的装配机制
- 1.2 自动配置的两种方式
- 2. 利用注解实现自动配置
- 2.1 @Autowired
- 2.2 @Qualifier
- 2.3 @Resource
- 3. 总结
1. 前言
1.1 Spring 的装配机制
自动装配指使用 Spring 满足 Bean 依赖的一种方法,Spring 会在应用上下文中为某个 Bean 寻找其依赖的 Bean,主要有三种装配机制:
- XML 中显式配置;
- Java 中显式配置;
- 隐式的 Bean 发现机制和自动装配;
而 Spring 的自动装配主要从两方面来实现:
- 组件扫描:Component Scanning,Spring 自动发现应用上下文中所创建的 Bean。
- 自动装配:Autowiring,Spring 自动满足不同 Bean 之间的依赖,即 IoC/DI.
1.2 自动配置的两种方式
- byName
<bean id="user" class="com.cunyu.pojo.User" autowire="byName">
<property name="name" value="村雨遥"/>
</bean>
按名称自动装配,在配置 Bean 时,加入一个 autowire
属性值 byName
。此时,Spring 将先去查找类中所有的 Setter
方法,然后去 Spring 容器中寻找是否有该字符串名称 id
的对象相匹配,如果找到了,就取出注入;若是没有找到,那么就报空指针异常。
- byType
按类型自动装配,在配置 Bean 时,加入一个 autowire
属性值 byType
。此时需要有一个 前提条件:同一类型的对象,在 Spring 容器中有且只有一个,否则就会报错。此时,Spring 将去查找类中所有的 Setter
方法,然后在 Spring 容器查找是否有该字符串名称 id
的对象,找到匹配的对象就取出注入,否则就抛出空指针异常。
2. 利用注解实现自动配置
2.1 @Autowired
@Autowired
按照类型(byType
)自动配置,不支持 id
匹配。
- 去掉
set
方法,利用@Autowired
进行注解;
public class User{
@Autowired
private Address address;
public Address getAddress(){
return address;
}
}
- 配置 Spring 配置文件;
<context:annotation-config/>
<bean id="addr" class="com.cunyu.pojo.Address"/>
<bean id="user" class="com.cunyu.pojo.User"/>
2.2 @Qualifier
@Qualifier
不能单独使用,需要配合 @Autowired
使用,从而实现按名称(byName
)自动配置。
- 在属性中添加
@Qualifier
public class User{
@Autowired
@Qualifier(value="addr2")
private Address address;
public Address getAddress(){
return address;
}
}
- 配置 Spring 配置文件;
<context:annotation-config/>
<bean id="addr" class="com.cunyu.pojo.Address"/>
<bean id="addr2" class="com.cunyu.pojo.Address"/>
<bean id="user" class="com.cunyu.pojo.User"/>
2.3 @Resource
@Resource
默认按照名称 byName
的方式进行装配,但如果有指定的 name
属性,则 优先 按照指定属性进行 byName
的方式查找并装配。
- 优先
byName
- 属性配置
@Resource
public class User{
// 指定 name 属性,先按照该属性进行按名称自动装配
@Resource(name = "addr2")
private Address address;
}
- 配置 Spring 配置文件
<context:annotation-config/>
<bean id="addr" class="com.cunyu.pojo.Address"/>
<bean id="addr2" class="com.cunyu.pojo.Address"/>
<bean id="user" class="com.cunyu.pojo.User"/>
- 默认
byType
- 属性配置
@Resource
public class User{
// 先 byName 查找失败,然后 byType 查找成功
@Resource
private Address address;
}
- 配置 Spring 配置文件
<context:annotation-config/>
<bean id="addr" class="com.cunyu.pojo.Address"/>
<bean id="user" class="com.cunyu.pojo.User"/>
3. 总结
@Autowired
和 @Resource
两者的作用相同,都是利用注解方式注入对象,均支持装配 Bean,都可以写在字段上,或者写在 setter
方法上。
@Autowired
属于 Spring 规范,默认按类型(byType
)装配,默认情况下要求依赖对象必须存在。若要允许 null
,则可设置其 required = false
,若想要按名称(byName
)装配,则可以搭配 @Qualifier
共同使用。
@Resource
属于 J2EE 规范,默认按名称(byName
)装配,名称可以通过 name
属性来指定。如果没有 name
属性,则当该注解写在 字段 上时,默认 取字段名 进行按名称(byName
)查找,如果注解写在 setter 方法 上,则默认取 属性名 进行装配。当找不到与名称匹配的 Bean 时才按类型(byType
)装配。但是需要注意的是,如果 name
属性一旦指定,就只会按照名称进行装配。
两者执行顺序不同,@Autowired
优先 byType
,若要实现 byName
,需要搭配 @Qualifier
,而 @Resource
优先 byName
,找不到匹配的 Bean 时,再 byType
。
- 我的WCF之旅(4):WCF中的序列化[上篇]
- WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]
- 微信年度重磅“小游戏”上线,罗胖一度退出的小程序正在逆袭
- 谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持
- Android注解学习(1)
- [WCF权限控制]ASP.NET Roles授权[上篇]
- [WCF权限控制]ASP.NET Roles授权[下篇]
- 如何解决分布式系统中的跨时区问题[实例篇]
- Visual Studio对程序集签名时一个很不好用的地方
- 一个关于解决序列化问题的编程技巧
- [WCF权限控制]从两个重要的概念谈起:Identity与Principal[上篇]
- 从数据到代码——通过代码生成机制实现强类型编程[下篇]
- 谈谈你最熟悉的System.DateTime[下篇]
- 如何解决EnterLib异常处理框架最大的局限——基于异常"类型"的异常处理策略
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 基于TypeScript封装Axios笔记(三)
- hadoop伪分布式之启动HDFS并运行MR程序(WordCount)
- 细品Reids的HyperLogLog数据结构
- 布隆过滤器与缓存击穿
- spring之通过注解方式配置Bean(二)
- 【python-leetcode103-树的宽度遍历】二叉树的锯齿形层次遍历
- 图卷积网络(GCN)python实现
- hadoop伪分布式之配置yarn并运行MR程序(WordCount)
- 【python-leetcode637-树的宽度遍历】二叉树的层平均值
- graphSAGE的python实现
- 【python-leetcode111-树的宽度遍历】二叉树的最小深度
- 基于TypeScript封装Axios笔记(四)
- spring之泛型依赖注入
- 【python-leetcode113-树的深度遍历】路径总和Ⅱ
- spring之为什么要使用AOP(面向切面编程)?