Spring Autowired原理
今天来整理一下Spring的自动装配 autowire一节,在这里我们要解决以下问题:
- 什么是自动装配?
- 自动装配的意义?
- 自动装配有几种类型?
- 如何启用自动装配?
- 自动装配将引发的问题?
一、什么是自动装配?
The Spring container is able to autowire relationships between collaborating beans. This means that it is possible to automatically let Spring resolve collaborators (other beans) for your bean by inspecting the contents of the BeanFactory.
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系。因此,如果可能的话,可以自动让Spring通过检查BeanFactory中的内容,来替我们指定bean的协作者(其他被依赖的bean)。
简而言之,就是对于bean当中引用的其他bean不需要我们自己去配置它改使用哪个类,Spring 的自动装配可以帮助我们完成这些工作。
二、自动装配的意义?
It is important to understand the various advantages and disadvantages of autowiring. Some advantages of autowiring include:
- Autowiring can significantly reduce the volume of configuration required. However, mechanisms such as the use of a bean template (discussed elsewhere in this chapter) are also valuable in this regard.
- Autowiring can cause configuration to keep itself up to date as your objects evolve. For example, if you need to add an additional dependency to a class, that dependency can be satisfied automatically without the need to modify configuration. Thus there may be a strong case for autowiring during development, without ruling out the option of switching to explicit wiring when the code base becomes more stable.
理解自动装配的优缺点是很重要的。其中优点包括:
- 自动装配能显著减少配置的数量。不过,采用bean模板(见这里)也可以达到同样的目的。
- 自动装配可以使配置与java代码同步更新。例如,如果你需要给一个java类增加一个依赖,那么该依赖将被自动实现而不需要修改配置。因此强烈推荐在开发过程中采用自动装配,而在系统趋于稳定的时候改为显式装配的方式。
三、 自动装配有几种类型?
- no
No autowiring at all. Bean references must be defined via a refelement. This is thedefault,and changing this is discouraged for larger deployments, since explicitly specifying collaborators gives greater control and clarity. To some extent, it is a form of documentation about the structure of a system.
- byName
Autowiring by property name. This option will inspect the container and look for a bean named exactly the same as the property which needs to be autowired. For example, if you have a bean definition which is set to autowire by name, and it contains a master property(that is, it has a setMaster(..) method), Spring will look for a bean definition named master, and use it to set the property.
- byType
Allows a property to be autowired if there is exactly one bean of the property type in the container. If there is more than one, a fatal exception is thrown, and this indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens; the property is not set. If this is not desirable, setting the dependency-check="objects"
attribute value specifies that an error should be thrown in this case.
- constructor
This is analogous to byType, but applies to constructor arguments. If there isn't exactly one bean of the constructor argument type in the container, a fatal error is raised.
- autodetect
Chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode will be applied.
- no
默认不使用autowiring。 必须显示的使用""标签明确地指定bean合作者,对于部署给予更大的控制和明了。
- byName
根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。例如,在bean定义中将 autowire设置为by name,而该bean包含master属性(同时提供setMaster(..)方法),Spring就会查找名为master的bean定义,并用它来装配给master属性。
- byType
如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置dependency-check="objects"让Spring抛出异常。
- constructor
与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
- autodetect
通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。
四、 如何启用自动装配?
你可以参照以下的配置去启用自动装配
<xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
default-autowire="byType" >
当然,这里的byType你可以更改为其他你想要的装配类型。
五、自动装配将引发的问题?
Some disadvantages of autowiring:
• Autowiring is more magical than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity which might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
• Wiring information may not be available to tools that may generate documentation from a Spring container.自动装配的一些缺点:
- 尽管自动装配比显式装配更神奇,但是,正如上面所提到的,Spring会尽量避免在装配不明确的时候进行猜测,因为装配不明确可能出现难以预料的结果,而且Spring所管理的对象之间的关联关系也不再能清晰的进行文档化。
- 对于那些根据Spring配置文件生成文档的工具来说,自动装配将会使这些工具没法生成依赖信息。
- 自动装配可以减轻配置的工作量,但同时使得配置文件的可读性变得很差,因为你不可能从配置文件中获知这些对象之间得依赖关系,从而维护困难!
注意: 
当根据类型进行自动装配的时候,容器中可能存在多个bean定义跟自动装配的setter方法和构造器参数类型匹配。这样就会存在模棱两可的问题。如果bean定义不唯一,装配时就会抛出异常。
解决方案(任选其一):
- 放弃使用自动装配,使用显示装配。
- 将bean排除在自动装配之外,
两个功能:
1 通过设定bean定义中的'autowire-candidate'属性显式的设置为'true' 或 'false'来设置其是否为被自动装配对象。 
2 使用对bean名字进行模式匹配来对自动装配进行限制,其做法是在元素的 'default-autowire-candidates' 属性中进行设置。可以使用通配符,如以'Repository'结尾的bean, 
那么可以设置为"*Repository“。
3 通过在bean定义中设置'primary'属性为'true'来将该bean设置为首选自动装配bean。
AnnotationConfigBeanDefinitionParser
AnnotationConfigUtils
AutowiredAnnotationBeanPostProcessor public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) { Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
} if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
} if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
} return beanDefs;
} 这里:有Autowired和Value
AutowiredAnnotationBeanPostProcessor:
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Spring Autowired原理的更多相关文章
- Spring 注解原理(三)@Qualifier @Value
		Spring 注解原理(三)@Qualifier @Value Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.Aut ... 
- Spring 注解原理(一)组件注册
		Spring 注解原理(一)组件注册 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 当我们需要使用 Spring 提供的 ... 
- Spring学习 6- Spring MVC (Spring MVC原理及配置详解)
		百度的面试官问:Web容器,Servlet容器,SpringMVC容器的区别: 我还写了个文章,说明web容器与servlet容器的联系,参考:servlet单实例多线程模式 这个文章有web容器与s ... 
- Spring事务原理分析--手写Spring事务
		一.基本概念和原理 1.Spring事务 基于AOP环绕通知和异常通知的 2.Spring事务分为编程式事务.声明事务.编程事务包括注解方式和扫包方式(xml) Spring事务底层使用编程事务(自己 ... 
- Spring事务原理分析-部分二
		Spring事务原理分析-部分二 说明:这是我在蚂蚁课堂学习了余老师Spring手写框架的课程的一些笔记,部分代码代码会用到余老师的课件代码.这不是广告,是我听了之后觉得很好. 课堂链接:Spring ... 
- 30个类手写Spring核心原理之动态数据源切换(8)
		本文节选自<Spring 5核心原理> 阅读本文之前,请先阅读以下内容: 30个类手写Spring核心原理之自定义ORM(上)(6) 30个类手写Spring核心原理之自定义ORM(下)( ... 
- Spring工作原理
		一. IoC(Inversion of control): 控制反转1.IoC:概念:控制权由对象本身转向容器:由容器根据配置文件去创建实例并创建各个实例之间的依赖关系核心:bean工厂:在Sprin ... 
- spring MVC原理
		spring MVC原理 Spring MVC工作流程图 图一 图二 Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt D ... 
- 【Spring】Spring IOC原理及源码解析之scope=request、session
		一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ... 
随机推荐
- Oracle入门第五天(上)——数据库对象之视图
			一.概述 1.什么是视图(VIEW) 视图 从表中抽出的逻辑上相关的数据集合(是一张虚表). 2.为什么使用视图 1.控制访问 2.简化查询 3.视图的分类 二.视图管理 1.创建视图 CREATE ... 
- Linux 用C语言实现简单的shell(1)
			发一波福利,操作系统的实验内容,大家可以借鉴一下,不过我的代码可能也存在一定的问题. 因为在一开始老师是一节一节课教的,当时并不知道后面还会用输入输出重定向,管道等一系列问题,我的兴趣也不在这个方面也 ... 
- WPF中使用WindowChrome自定义窗口中遇到的最大化问题
			FrameWork 4.5 之后,内置了WindowChrome类,官方文档: https://msdn.microsoft.com/en-us/library/system.windows.shel ... 
- 3809: Gty的二逼妹子序列
			3809: Gty的二逼妹子序列 链接 分析: 和这道AHOI2013 作业差不多.权值是1~n的,所以对权值进行分块.$O(1)$修改,$O(\sqrt n)$查询. 代码: #include< ... 
- iOS 影音新格式 HEIF HEVC
			苹果在 iOS 11 的发布会上,推出了两种新的媒体格式 HEIF HEVC,都是为了保证画质的情况下,大大减少视频.照片的大小. 一.简介 HEVC全称 High Efficiency Video ... 
- HCIE理论-IPV6
			ipv4与ipv6的对比 IPv4 :32 bit 点分十进制 192.168.1.1 2^32=42.9亿 ipv4地址不足IPv6 :128 bit 十六进制 2^128 冒号分十六进制ipv4 ... 
- java 多路分发
			1.概念 一个函数处理多种类型,其实和多态差不多. 但是要处理两种或者多种类型的数据时,就需要判断每种类型以及每种类型所对应的处理.(PS:我只是在走别人的老路,网上一搜这种概念,博客一大堆,我不知道 ... 
- linux中生成考核用的NTFS文件系统结构样例
			实验NTFS-1说明:NTFS-1.img是一个包含NTFS文件系统的磁盘镜像,请使用winhex手工方式读出这个文件系统内的指定文件,并回答其md5 HASH值.要求: 1.利用WINHEX手工方式 ... 
- 阿里云服务器Centos上Apache安装SSL证书配置Https
			首先我们先去阿里云申请一个免费的SSL证书(https://common-buy.aliyun.com/?spm=5176.7968328.1266638..5e971232BzMSp5&co ... 
- 运输层(TCP/UDP)详解
			TCP和UDP的区别: tcp是面向连接的可靠的传输协议 udp是非连接的不可靠的传输协议 TCP组成 可以看到虽然tcp是面向字节流的,但是其传输的基本单位还是报文(tcp首部和数据,ip报文和ud ... 
