文章目录
什么是DI
DI (Dependency Injection),即依赖注入,其基本原则是应用组件不负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IOC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
举个例子:一个类A需要用到接口B中的方法,那么就需要为类A和接口B建立关联或依赖关系,最原始的方法是在类A中创建一个接口B的实现类C的实例,但这种方法需要开发人员自行维护二者的依赖关系,也就是说当依赖关系发生变动的时候需要修改代码并重新构建整个系统。如果通过一个容器来管理这些对象以及对象的依赖关系,则只需要在类A中定义好用于关联接口B的方法(构造器或setter方法),将类A和接口B的实现类C放入容器中,通过对容器的配置来实现二者的关联。
依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。
从一个简单的示例说起
package com.dom.dao;
public interface OrderDao {
public void save();
}
package com.dom.dao.impl;
import com.dom.dao.OrderDao;
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ...");
}
}
package com.dom.service;
public interface OrderService {
public void save();
}
App main函数时序图:
无DI的示例
package com.dom.service.impl;
import com.dom.dao.OrderDao;
import com.dom.dao.impl.OrderDaoImpl;
import com.dom.service.OrderService;
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao = new OrderDaoImpl();
public void save() {
System.out.println("order service save ...");
orderDao.save();
}
}
App2 main函数:
package com.dom;
import com.dom.service.OrderService;
import com.dom.service.impl.OrderServiceImpl;
public class App2 {
public static void main(String[] args) {
OrderService orderService = (OrderService) new OrderServiceImpl();
orderService.save();
}
}
运行结果:
有DI的示例(XML版)
- build.gradle需导入坐标:
dependencies {
compile(project(":spring-context"))
testCompile group: 'junit', name: 'junit', version: '4.12'
}
- applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.导入spring的坐标spring-context,对应版本是5.2.19.RELEASE-->
<!--2.配置bean-->
<!--bean标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型-->
<bean id="orderDao" class="com.dom.dao.impl.OrderDaoImpl"/>
<bean id="orderService" class="com.dom.service.impl.OrderServiceImpl">
<!--7.配置service与dao的关系-->
<!--property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean-->
<property name="orderDao" ref="orderDao"/>
</bean>
</beans>
- Service依赖注入orderDao Bean
package com.dom.service.impl;
import com.dom.dao.OrderDao;
import com.dom.service.OrderService;
public class OrderServiceImpl implements OrderService {
//5.删除业务层中使用new的方式创建的dao对象
private OrderDao orderDao;
public void save() {
System.out.println("order service save ...");
orderDao.save();
}
//6.提供对应的set方法
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
- DIXMLApp main函数:
package com.dom;
import com.dom.service.OrderService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DIXMLApp {
public static void main(String[] args) {
//3.获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean(根据bean配置id获取)
OrderService orderService = (OrderService) ctx.getBean("orderService");
System.out.println("orderService:: " + orderService);
orderService.save();
}
}
- 运行结果:
总结起来,在spring中获取bean,从应用层面共需要这六个步骤:
- 导入spring的坐标spring-context
- 配置bean
- 获取IOC容器
- 获取bean(根据bean配置id获取)
- 提供对应的set方法
- 配置service与dao的关系
在获取IOC容器这一步骤中,程序代码为:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml")
将实现IOC容器的创建和刷新工作,以及容器中需要管理的全部对象的bean创建,实例化,属性填充(依赖注入DI)以及其初始化等工作。
本文将详细讲述属性填充这部分。
有DI的示例(纯注解版)
- 首先移除上述定义bean的XML配置文件applicationContext.xml
- 对OrderDaoImpl和OrderServiceImpl使用注解@Component,使spring IOC容器识别,对它们实现bean的创建和管理。
- 在OrderServiceImpl类中,对其成员bean orderDao加入注解@Autowired,使其自动依赖注入(DI)
- 增加一个spring配置类SpringConfig,用于spring IOC容器将扫描那些包含注解的package,其实就是根据注解的定义去识别和管理bean,从而用注解取代前面的XML配置bean。
- 创建一个新的应用DiAnnotationApp1,将原来使用ClassPathXmlApplicationContext获取IOC容器的方法替换成AnnotationConfigApplicationContext。
如下面的代码和运行结果所示:
public interface OrderDao {
public void save();
}
@Component
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ...");
}
}
public interface OrderService {
public void save();
}
@Component(value="orderService")
public class OrderServiceImpl extends OrderDaoImpl implements OrderService {
@Autowired
private OrderDao orderDao;
public void save() {
System.out.println("order service save ...");
orderDao.save();
}
}
@Configuration
@ComponentScan({"com.dom.service","com.dom.dao"})
public class SpringConfig {
}
public class DiAnnotationApp1 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
OrderService orderService = (OrderService) ctx.getBean("orderService");
System.out.println("orderService:: " + orderService);
orderService.save();
}
}
代码运行结果:
Spring中DI的过程概述
Spring中DI的实现,就在populateBean()的执行中,其过程图:
1. 基于XML配置
2. 基于纯注解
简述一下populateBean()的处理过程:
1、针对bean的包装器是否为空、是否存在为此 bean 定义的属性值,做不同的处理。如果bean的包装器为空,但是又存在为此 bean 定义的属性值,Spring则会抛出BeanCreationException异常;如果没有为此 bean 定义的属性值,即没有可填充的属性,则直接返回;
2、如果bean定义不是合成的,并且工厂中存在创建时应用于单例 bean 的 InstantiationAwareBeanPostProcessor后置处理器,则需要处理执行它的postProcessAfterInstantiation()方法;
3、获取到bean定义中封装好的属性值;
4、根据设置的自动注入方式(名称或者类型)获取属性bean(递归getBean)存入PropertyValues中;
5、如果存在InstantiationAwareBeanPostProcessor后置处理器,需要执行InstantiationAwareBeanPostProcessor的postProcessProperties()以及postProcessPropertyValues()方法回调;
6、执行依赖检查,对应depend-on属性;
7、属性填充的具体过程,即将属性值赋值到beanWrapper中bean实例的具体属性中;
IOC容器的依赖注入DI(源码分析)
(基于Spring 5.2.19.RELEASE)
1. 基于XML配置
1.1. populateBean方法对Bean属性的依赖注入
在Bean的依赖注入前,其实还有一个生成Bean所包含的java对象实例的过程,即createBeanInstance。由于内容较多,我将把这部分放到我的另一篇文章关于Bean的完整生命过程中作详细的讲述。
而本文就spring源码一步一步去分析和讲述populateBean这块,Spring IoC容器是如何将Bean的属性依赖关系注入Bean实例对象中并设置好的,属性依赖注入的代码如下:
//将Bean属性设置到生成的实例对象上
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 1、针对bean的包装器是否为空、是否存在为此 bean 定义的属性值,做不同的处理
if (bw == null) {
// 如果bean的包装器为空,但是又存在为此 bean 定义的属性值,Spring则会抛出BeanCreationException异常
// 因为属性填充就是要给BeanWrapper 中的 bean 实例中的属性进行赋值的过程,存在属性,但是BeanWrapper为空,也就是BeanWrapper 中的 bean 实例为空,那么显然不行
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// 如果没有为此 bean 定义的属性值,即没有可填充的属性,则直接返回
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// InstantiationAwareBeanPostProcessor后置处理器:可以在属性设置前修改bean
// 2、如果bean定义不是合成的,并且工厂中存在创建时应用于单例 bean 的 InstantiationAwareBeanPostProcessor后置处理器,则需要处理执行它的postProcessAfterInstantiation()方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 获取到bean工厂所有已经注册的BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 判断是否属于InstantiationAwareBeanPostProcessor类型
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果类型匹配的话,将会执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法
// postProcessAfterInstantiation()方法:在bean实例化后,属性填充之前被调用,允许修改bean的属性,默认实现是返回true
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
// 如果postProcessAfterInstantiation()方法返回false,则跳过后面的属性填充过程
return;
}
}
}
}
// 3、获取到bean定义中封装好的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 4、根据设置的自动注入方式(名称或者类型)获取属性bean(递归getBean)存入PropertyValues中
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动注入
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根据类型自动注入
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// hasInstAwareBpps:工厂是否存在将在创建时应用于单例 bean 的 InstantiationAwareBeanPostProcessor后置处理器
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// needsDepCheck:是否需要进行依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
// 5、如果存在InstantiationAwareBeanPostProcessor后置处理器,需要执行InstantiationAwareBeanPostProcessor的postProcessProperties()以及postProcessPropertyValues()方法回调
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 执行InstantiationAwareBeanPostProcessor的postProcessProperties()以及postProcessPropertyValues()方法回调
// postProcessProperties(): 允许对填充前的属性进行处理(如对属性的验证)
// postProcessPropertyValues(): 对属性值进行修改,通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值。
// 不过目前方法已经被标记为过期,在后续Spring版本中可能会被删除
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
// 6、执行依赖检查,对应depend-on属性
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 依赖检查,对应depend-on属性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 7、属性填充的具体过程,即将属性值赋值到beanWrapper中bean实例的具体属性中
if (pvs != null) {
// 开始填充属性值
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
//解析并注入依赖属性的过程
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
//封装属性值
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//属性值已经转换
if (mpvs.isConverted()) {
try {
//为实例化对象设置属性值
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
//获取属性值对象的原始类型值
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
//获取用户自定义的类型转换
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//创建一个Bean定义属性值解析器,将Bean定义中的属性值解析为Bean实例对象的实际值
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
//为属性的解析值创建一个拷贝,将拷贝的数据注入到实例对象中
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
//属性值不需要转换
if (pv.isConverted()) {
deepCopy.add(pv);
}
//属性值需要转换
else {
String propertyName = pv.getName();
//原始的属性值,即转换之前的属性值
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
//转换属性值,例如将引用转换为IoC容器中实例化对象引用
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//转换之后的属性值
Object convertedValue = resolvedValue;
//属性值是否可以转换
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
//使用用户自定义的类型转换器转换属性值
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
//存储转换后的属性值,避免每次属性注入时的转换工作
if (resolvedValue == originalValue) {
if (convertible) {
//设置属性转换之后的值
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
//属性是可转换的,且属性原始值是字符串类型,且属性的原始类型值不是
//动态生成的字符串,且属性的原始值不是集合或者数组类型
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
//重新封装属性的值
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
//标记属性值已经转换过
mpvs.setConverted();
}
//进行属性依赖注入
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
分析上述代码,我们可以看出,对属性的注入过程分以下两种情况:
(1).属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。
(2).属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。
对属性值的解析是在BeanDefinitionValueResolver类中的resolveValueIfNecessary方法中进行的,对属性值的依赖注入是通过bw.setPropertyValues方法实现的,在分析属性值的依赖注入之前,我们先分析一下对属性值的解析过程。
1.2. BeanDefinitionValueResolver解析属性值
当容器在对属性进行依赖注入时,如果发现属性值需要进行类型转换,如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上去,对属性进行解析的由resolveValueIfNecessary方法实现,其源码如下:
//解析属性值,对注入类型进行转换
public Object resolveValueIfNecessary(Object argName, Object value) {
//对引用类型的属性进行解析
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//调用引用类型属性的解析方法
return resolveReference(argName, ref);
}
//对属性值是引用容器中另一个Bean名称的解析
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(evaluate(refName));
//从容器中获取指定名称的Bean
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
//对Bean类型属性的解析,主要是Bean中的内部类
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
}
else if (value instanceof DependencyDescriptor) {
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
Object result = this.beanFactory.resolveDependency(
(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
for (String autowiredBeanName : autowiredBeanNames) {
if (this.beanFactory.containsBean(autowiredBeanName)) {
this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
}
}
return result;
}
//对集合数组类型的属性解析
else if (value instanceof ManagedArray) {
ManagedArray array = (ManagedArray) value;
//获取数组的类型
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
//获取数组元素的类型
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
//使用反射机制创建指定类型的对象
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
//没有获取到数组的类型,也没有获取到数组元素的类型,则直接设置数
//组的类型为Object
else {
elementType = Object.class;
}
}
//创建指定类型的数组
return resolveManagedArray(argName, (List<?>) value, elementType);
}
//解析list类型的属性值
else if (value instanceof ManagedList) {
return resolveManagedList(argName, (List<?>) value);
}
//解析set类型的属性值
else if (value instanceof ManagedSet) {
return resolveManagedSet(argName, (Set<?>) value);
}
//解析map类型的属性值
else if (value instanceof ManagedMap) {
return resolveManagedMap(argName, (Map<?, ?>) value);
}
//解析props类型的属性值,props其实就是key和value均为字符串的map
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
//创建一个拷贝,用于作为解析后的返回值
Properties copy = new Properties();
for (Map.Entry propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
copy.put(propKey, propValue);
}
return copy;
}
//解析字符串类型的属性值
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
//获取属性的目标类型
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
//对目标类型的属性进行解析,递归调用
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
//没有获取到属性的目标对象,则按Object类型返回
else {
return valueObject;
}
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else {
return evaluate(value);
}
}
//解析引用类型的属性值
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
//获取引用的Bean名称
Class<?> beanType = ref.getBeanType();
//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean " + ref +
" in parent factory: no parent factory available");
}
//从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化
//则会递归触发引用Bean的初始化和依赖注入
if (beanType != null) {
bean = parent.getBean(beanType);
}
else {
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
}
}
else {
String resolvedName;
if (beanType != null) {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
}
else {
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
bean = this.beanFactory.getBean(resolvedName);
}
//将当前实例化对象的依赖引用对象
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
//解析array类型的属性
private Object resolveManagedArray(Object argName, List<?> ml, Class elementType) {
//创建一个指定类型的数组,用于存放和返回解析后的数组
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
//递归解析array的每一个元素,并将解析后的值设置到resolved数组中,索引为i
Array.set(resolved, i,
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
//解析list类型的属性
private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
//递归解析list的每一个元素
resolved.add(
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
//解析set类型的属性
private Set resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
int i = 0;
//递归解析set的每一个元素
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
i++;
}
return resolved;
}
//解析map类型的属性
private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<>(mm.size());
//递归解析map中每一个元素的key和value
mm.forEach((key, value) -> {
Object resolvedKey = resolveValueIfNecessary(argName, key);
Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, key), value);
resolved.put(resolvedKey, resolvedValue);
});
return resolved;
}
通过上面的代码分析,我们明白了Spring是如何将引用类型,内部类以及集合类型等属性进行解析的,属性值解析完成后就可以进行依赖注入了,依赖注入的过程就是Bean对象实例设置到它所依赖的Bean对象属性上去,在第7步中我们已经说过,依赖注入是通过bw.setPropertyValues方法实现的,该方法也使用了委托模式,在BeanWrapper接口中至少定义了方法声明,依赖注入的具体实现交由其实现类BeanWrapperImpl来完成,下面我们就分析依BeanWrapperImpl中赖注入相关的源码。
1.3. BeanWrapperImpl对Bean属性的依赖注入
BeanWrapperImpl类主要是对容器中完成初始化的Bean实例对象进行属性的依赖注入,即把Bean对象设置到它所依赖的另一个Bean的属性中去,依赖注入的相关源码如下:
//解析值会将 <property> 标签中设置的 value 进行解析,而且在这边如果有 json 类型或者数组类型的值传入,
// 还会进行下标值的解析。通过是否有下标值来判断具体该执行普通的获取值的方法还是需要使用下标值来获取具体值的方法。
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex);
}
// 如果是解析到数组或者json之类的,则会获取其中的下标值
tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
if (nestedPa == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
// 会根据解析获取到的 token 来进行判断
nestedPa.setPropertyValue(tokens, pv);
}
else {
// 会根据解析获取到的 token 来进行判断
setPropertyValue(tokens, pv);
}
}
/*
如果在之前解析到下标值并封装成 token,则会在这边根据下标值的有无实行不同的方法。
普通的 Bean 注入会走 processLocalProperty();如果遇到 param[0] 或者 param[index] 之类的则会走 processKeyedProperty()。
*/
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
if (tokens.keys != null) {
//如果遇到 param[0] 或者 param[index] 之类的注入
processKeyedProperty(tokens, pv);
}
else {
//普通的Bean注入
processLocalProperty(tokens, pv);
}
}
//进行普通的Bean注入
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null || !ph.isWritable()) {
if (pv.isOptional()) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring optional value for property '" + tokens.actualName + "' - property not found on bean class [" + getRootClass().getName() + "]");
}
return;
}
else {
throw createNotWritablePropertyException(tokens.canonicalName);
}
}
Object oldValue = null;
try {
// 获取属性值
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
valueToApply = pv.getConvertedValue();
}
else {
// 获取值
if (isExtractOldValueForEditor() && ph.isReadable()) {
try {
oldValue = ph.getValue();
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" + this.nestedPath + tokens.canonicalName + "'", ex);
}
}
}
// 进行类型转换
valueToApply = convertForProperty(tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 这边会有两种类型注入,一种是通过方法进行注入,还有一种是通过类的属性直接设置
ph.setValue(valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
}
else {
Throwable cause = ex.getTargetException();
if (cause instanceof UndeclaredThrowableException) {
cause = cause.getCause();
}
throw new MethodInvocationException(propertyChangeEvent, cause);
}
}
catch (Exception ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(
getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
//通过方法进行注入
@Override
public void setValue(@Nullable Object value) throws Exception {
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
//根据权限修改属性的读取控制限制,暴力执行非public方法
ReflectionUtils.makeAccessible(writeMethod);
//通过反射,调用方法进行注入
writeMethod.invoke(getWrappedInstance(), value);
}
}
}
//另一种方式通过Field属性注入
@Override
public void setValue(@Nullable Object value) throws Exception {
try {
//根据权限修改属性的读取控制限制,暴力执行非public方法
ReflectionUtils.makeAccessible(this.field);
//通过反射,调用方法进行注入
this.field.set(getWrappedInstance(), value);
}
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(getWrappedClass(), this.field.getName(),
"Field is not accessible", ex);
}
}
}
通过对上面注入依赖代码的分析,我们已经明白了Spring IoC容器是如何将属性的值注入到Bean实例对象中去的:
(1).对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性。
(2).对于非集合类型的属性,大量使用了JDK的反射和内省机制,通过属性的getter方法(reader method)获取指定属性注入以前的值,同时调用属性的setter方法(writer method)为属性设置注入后的值。看到这里相信很多人都明白了Spring的setter注入原理。
至此Spring IoC容器对Bean定义资源文件的定位,载入、解析和依赖注入已经全部分析完毕,现在Spring IoC容器中管理了一系列靠依赖关系联系起来的Bean,程序不需要应用自己手动创建所需的对象,Spring IoC容器会在我们使用的时候自动为我们创建,并且为我们注入好相关的依赖,这就是Spring核心功能的控制反转和依赖注入的相关功能。
2. 基于纯注解
2.1. 属性收集
在AbstractAutowireCapableBeanFactory .doCreateBean函数中,含有一段逻辑就是在bean刚被容器对象实例化后,允许bean后置处理器对bean定义做修改,其代码如下:
// 允许后处理器修改合并的 bean 定义
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 应用合并后的BeanDefinition后置处理器:执行MergedBeanDefinitionPostProcessor后置处理器增强方法postProcessMergedBeanDefinition()
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
//应用合并后的BeanDefinition后置处理器
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
//后置处理和合并bean的定义
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
//后置处理合并bean定义的实现
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//查找autowire的元注解信息InjectionMetadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
查找元注解
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
//获取Bean的名字,如果没有以类名作为名字
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
//从自动注入元数据缓存map中查找InjectionMetadata
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//构建自动装配元数据,利用反射获取
metadata = buildAutowiringMetadata(clazz);
//缓存自动装配元数据
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
查找元注解比较简单,先从缓存中获取,如果缓存中没有就调用 buildAutowiringMetadata 查找元注解信息然后加入缓存。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//查找@autowired注解的属性,以及要注入的对象
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
//添加到 currElements 集合中
currElements.add(new AutowiredFieldElement(field, required));
}
});
...省略...,
//把注解封的属性封装成jectionMetadata
return new InjectionMetadata(clazz, elements);
}
根据Bean的class使用反射查找到Bean中的@Autowire注解信息,以及注入的Bean ,创建成 一个一个的AutowiredFieldElement ,封装到InjectionMetadata 返回。Element结构如下:
2.2. 属性填充判断
在上述populateBean的函数中,有这样一段代码:
此代码摘自本文1.1
// InstantiationAwareBeanPostProcessor后置处理器:可以在属性设置前修改bean
// 2、如果bean定义不是合成的,并且工厂中存在创建时应用于单例 bean 的 InstantiationAwareBeanPostProcessor后置处理器,则需要处理执行它的postProcessAfterInstantiation()方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 获取到bean工厂所有已经注册的BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 判断是否属于InstantiationAwareBeanPostProcessor类型
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果类型匹配的话,将会执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法
// postProcessAfterInstantiation()方法:在bean实例化后,属性填充之前被调用,允许修改bean的属性,默认实现是返回true
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
// 如果postProcessAfterInstantiation()方法返回false,则跳过后面的属性填充过程
return;
}
}
}
}
如下,这里调用了InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
方法来决定是否继续注入属性。该方法正常返回true。如果返回false 则将取消对此bean调用任何后续的InstantiationAwareBeanPostProcessor
方法。
2.3. 自动装配
在这段代码中,对AUTOWIRE_BY_NAME
类型和AUTOWIRE_BY_TYPE
的种类进行自动装配。
此代码摘自本文1.1
// 4、根据设置的自动注入方式(名称或者类型)获取属性bean(递归getBean)存入PropertyValues中
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动注入
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根据类型自动注入
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//postProcessAfterInstantiation():可以控制是否继续后面的属性填充过程,如果返回false,则跳过后面的属性填充过程,默认返回true
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
这一段代码的目的是,如果bean
在声明的时候指定了自动注入类型是byName
或者byType
,则会根据这个规则,对bean
内部的排除某些特定的属性后, 进行byName
或者byType
的自动装配。
2.3.1. 根据名字自动装配 - autowireByName
//autowireByName():根据名称自动注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 1、获取需要注入的属性名称数组,注意只获取不是“简单”属性类型(基础类型、枚举、Number等)的那些属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 2、循环需要注入的属性,根据名称自动注入
for (String propertyName : propertyNames) {
// 3、判断是否存在名称为propertyName的bean或者bean定义,如果当前工厂中没找到,还会递归所有的父工厂去查找
if (containsBean(propertyName)) {
// 4、通过getBean从工厂中获取到名称为propertyName的bean实例
Object bean = getBean(propertyName);
// 5、将propertyName以及对应的属性值bean添加到MutablePropertyValues中
pvs.add(propertyName, bean);
// 6、注册依赖关系到两个缓存中:dependentBeanMap、dependenciesForBeanMap
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
} else {
// 7、如果工厂以及父工厂都没有找到名称为propertyName的bean或者bean定义,则不处理这个属性
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
可以看到,byName
的处理逻辑很简单,一句话概括,获取需要注入的bean然后递归调用getBean获取bean进行注入。 关于unsatisfiedNonSimpleProperties
方法在后面有讲解。
注册依赖bean - registerDependentBean
// bean dependent(依赖的集合) : beanName -> 依赖该beanName 的 bean,即 key代表的bean 被value 所依赖
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
// bean 被哪些bean依赖 : beanName -> beanName 所依赖的 bean。即 key 依赖于value这些bean
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
/**
* 注册依赖关系的bean
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取真实的beanName
String canonicalName = canonicalName(beanName);
// 保存依赖关系。dependentBeanMap: key 被 value 依赖
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// bean被哪些bean依赖 dependenciesForBeanMap : key 依赖于bean
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
排除规则 - unsatisfiedNonSimpleProperties
在unsatisfiedNonSimpleProperties
方法中,对Bean
的属性进行了过滤,得到了需要自动装配的属性。我们来详细看看里面的内容。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
// 获取bean的property属性
PropertyValues pvs = mbd.getPropertyValues();
// 获取 bw 中的属性描述
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
// if pd属性具有set方法 && 依赖检查中没有被忽略 && 没有被配置成property属性 && 不是简单类型
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
// 添加到需要装配的集合中
result.add(pd.getName());
}
}
// 返回需要自动装配的bean集合
return StringUtils.toStringArray(result);
}
可以看到过滤条件
- 装配属性具有set 方法: 因为后面的装配是通过set方法装配
- 依赖检查中没有被忽略
- 没有property属性,因为这里property会被单独处理,不需要在这里保存
- 不是简单类型,即不属于Void、void、 Enum、CharSequence、Number、Date、Temporal、URI、URL、Locale、Class 和 八大基本数据类型及其包装类型。可以看到如下代码,ClassUtils.isPrimitiveOrWrapper(type) 判断是type是否属于基本数据类型或者其包装类型。
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
2.3.2. 根据类型自动装配 - autowireByType
//autowireByType():根据类型自动注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 1、判断是否存在自定义的TypeConverter,存在则使用自定义的,否则还是使用入参指定的bw
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 2、获取需要注入的属性名称数组,注意只获取不是“简单”属性类型(基础类型、枚举、Number等)的那些属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
// 3、获取包装对象的特定属性的属性描述符
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
// 4、为指定属性的写入方法获取一个新的 MethodParameter 对象,通常指的是获取setter方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 5、解析当前属性所匹配的bean实例,并把解析到的bean实例的beanName存入autowiredBeanNames
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 6、如果解析到的bean实例不为空的话,将propertyName以及对应的属性值autowiredArgument添加到MutablePropertyValues中
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 7、注册依赖关系到两个缓存中:dependentBeanMap、dependenciesForBeanMap,这里是beanName依赖了autowiredBeanName
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
这里面的主要的逻辑被封装到了resolveDependency()
方法中,我们下面来看看DefaultListableBeanFactory#resolveDependency
方法的具体实现。目前我所知另外调用地方:
AutowiredAnnotationBeanPostProcessor
中注入处理@Autowired
注入的时候也调用了该方法
ConstructorResolver#autowireConstructor
在resolveAutowiredArgument( methodParam, beanName, autowiredBeanNames, converter, fallback);
时也调用了该方法。
解析依赖关系 - resolveDependency
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 针对不同类型的不同处理
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 处理bean是否懒加载,如果懒加载,创建一个代理对象注入bean
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 针对一般类型的通用
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
上面的逻辑比较清晰,对一些特殊的类型进行特殊处理,一般的通用处理都会调用 doResolveDependency()
方法。这里我们不去关注特殊类型的处理,下面再来看看
DefaultListableBeanFactory#doResolveDependency()
方法,代码如下。
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 只有ShortcutDependencyDescriptor实现了resolveShortcut方法,返回了非空值。目前版本代码只在AutowiredFieldElement、
// AutowiredMethodElement类中使用到,也即是说,只有解析@Autowired、@Value注解的元素才会用到,目的是为了将解析结果缓存起来,避免重复解析
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 尝试获取缓存
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
// 存在缓存直接返回
return shortcut;
}
// 获取依赖的类型
Class<?> type = descriptor.getDependencyType();
// 取值@Value注解中的value属性中的值,这里取出的值是未经修改的值,即带有 ${} 标签的值。如果descriptor未被@Value标注,则返回null
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
// 到这里说明属性被@Value注解修饰了,这里是解析@Value注解的逻辑
// 如果value不为null,
if (value instanceof String) {
// 处理占位符如${},做占位符的替换(不解析SP EL表达式)
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
// 解析SP EL(如#{})
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
// 类型转换,把解析出来的结果转成type类型
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
// 对集合类型进行处理,包括,Array、Collection、Map。后面详解
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
// 如果解析出来集合类型,则直接返回
return multipleBeans;
}
// 调用查找所有类型为type的实例,存放在matchingBeans<beanName, bean> (在resolveMultipleBeans方法中也是核心也是调用该方法)。下面详解
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
// 如果没有找到,并且bean并标注为required=true, 则抛出NoSuchBeanDefinitionException异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果找到了不止一个匹配的bean,Spring 按照一定规则进行挑选
if (matchingBeans.size() > 1) {
// 按以下顺序,找到符合条件的就直接返回
// 1. 挑选出被标识为primary的bean
// 2. 挑选标识了@Priority,且先级级最高的bean。可以不标识,一旦标识,不允许同一优先级的存在
// 3. fallback,依赖的名称与matchingBeans中任意一Key匹配
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
// 非集合类,找到了多个符合条件的Bean,抛出异常
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
// 如果只找到了唯一匹配的元素,则直接使用
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
// 将待装配的Bean名称放入autowiredBeanNames集合里
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 这里又去调用 getBean 方法去获取bean
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
// 如果 result 是 NullBean类型,且 required = true,则抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
// 类型校验,确保类型与解析出来的Bean实例能够匹配
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
// 获取类型
Class<?> requiredType = descriptor.getDependencyType();
// 获取primary的候选beanName
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 获取Priority最高(优先级最高的)beanName
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 通过回调返回。
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
//这个方法是用来处理 数组、Collection、Map 类型的注入
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
//如果descriptor是 StreamDependencyDescriptor实例
if (descriptor instanceof StreamDependencyDescriptor) {
// 根据StreamDependencyDescriptor找到beanFactory中匹配的bean
// 返回值构成:key = 匹配的beanName, value = beanName对应的实例化bean,通过getBean(beanName)获取。
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 保存所有适配的 beanName
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
// 如果是 数组类型
else if (type.isArray()) {
// 确定最终类型
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
// 根据属性类型找到beanFactory中所有类型的匹配bean
// 返回值构成:key = 匹配的beanName, value = beanName对应的实例化bean,通过getBean(beanName)获取。
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
// 如果是未找到匹配的bean,则返回null,
if (matchingBeans.isEmpty()) {
return null;
}
// 保存所有适配的 beanName
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
// 进行类型转换,将bean转换为对应的type类型。
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[]) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
// 排序
Arrays.sort((Object[]) result, comparator);
}
}
return result;
}
// 对Collection类型的处理,逻辑基本同上,这里不再赘述
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
if (((List<?>) result).size() > 1) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
}
// 对map类型的处理,逻辑类似上面
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
可以看到的是,如果是集合类型,内部的核心方法也是findAutowireCandidates
方法。所以下面还是来看DefaultListableBeanFactory#findAutowireCandidates()
方法。
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 根据 Class 类型,找到对应的候选beanName,
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 这里我们一般不会涉及。如果注入的是 resolvableDependencies key类型,则会装配成value类型
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 遍历候选的beanName
for (String candidate : candidateNames) {
// 不是自引用 && 允许被注入(autowire-candidate 标签指定)
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
// 将结果添加到result中
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 如果目前找到的匹配的bean集合为空 && Array || Collection || Map 。即是否表示多个bean的集合类型
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
// 非自引用 && 允许被注入 && (非集合类 || 解析 @Qualifier 注解或者 javax.inject.Qualifier类成功)
// 这里开始分析解析的属性是否被 @Qualifier 注解或者 javax.inject.Qualifier类 限定符限定了
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 如果还没找到
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
// 将自我引用视为最后一步。判断是不是自己引用自己
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
// 根据类型判断,如果是MultiElementDescriptor,获取后保存到候选列表中
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
// getType 调用了beanFacotory.getBean()方法
candidates.put(candidateName, getType(candidateName));
}
}
这里提两点:
- 这里需要注意
resolvableDependencies
。其在DefaultListableBeanFactory#resolvableDependencies()
定义如下,其作用是,当一些其他的类需要装配key类型的bean时,实际装配的类型是key对应的value 类型。
/** Map from dependency type to corresponding autowired value. */
// key 是映射值,value是实际注入值
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
在此应用的Spring默认代码中,有四个元素保存到resolvableDependencies,如下:
如下, DemoforBeanFactory
默认装配的BeanFactory
类型是DefaultListableBeanFactory
类型:
@Component
public class DemoforBeanFactory {
@Autowired
private DemoA demoA;
@Autowired
private DemoB demoB;
@Autowired
private List<DemoC> demos;
@Autowired
private BeanFactory beanFactory;
}
2.4. 属性注入
此代码摘自本文1.1
// 5、如果存在InstantiationAwareBeanPostProcessor后置处理器,需要执行InstantiationAwareBeanPostProcessor的postProcessProperties()以及postProcessPropertyValues()方法回调
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 执行InstantiationAwareBeanPostProcessor的postProcessProperties()以及postProcessPropertyValues()方法回调
// postProcessProperties(): 允许对填充前的属性进行处理(如对属性的验证)
// postProcessPropertyValues(): 对属性值进行修改,通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值。
// 不过目前方法已经被标记为过期,在后续Spring版本中可能会被删除
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//查找找 autowire 元数据,利用反射根据bean的class得到bean的元注解信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//得到要注入的属性集合
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
//调用InjectedElement的inject方法注入
element.inject(target, beanName, pvs);
}
}
}
//属性反射注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
//【重要】给autoware的字段设置值,完成自动注入
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
//DependencyDescriptor 依赖描述符
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
//类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
//得到容器中的Bean实例
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
//走缓存流程
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
//注册依赖的Bean
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//ShortcutDependencyDescriptor:具有预先解析的目标 bean 名称的 DependencyDescriptor 变体
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
}
//方法反射注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
try {
arguments = resolveCachedArguments(beanName);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
arguments = resolveMethodArguments(method, bean, beanName);
}
}
else {
arguments = resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) {
try {
//【重要】调用autoware注解的方法,完成自动注入
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
//处理方法参数
@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
int argumentCount = method.getParameterCount();
Object[] arguments = new Object[argumentCount];
//DependencyDescriptor 依赖描述符
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
//类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
//得到容器中的Bean实例
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
//注册依赖的Bean
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
//缓存方法参数
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
return arguments;
}
}
这里通过InstantiationAwareBeanPostProcessor
的后处理器的postProcessPropertyValues
方法完成了属性的注入。Spring 默认是通过 AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues()
的实现来完成的属性的注入。
AutowiredAnnotationBeanPostProcessor
中完成了@Autowired
、@Value
注解的自动注入功能。
其逻辑是,获取被@Autowired
修饰的属性或者方法,如果是属性,则通过getBean()
获取bean并注入,如果是方法,则获取方法参数后,invoke()
方法(调用该方法,因为我们一般写的都是set方法,给属性注入赋值)。