Bean 的加载步骤详解(二)
一、循环依赖
1、什么是循环依赖
循环依赖就是循环引用,即两个或多个 bean 互相之间持有对方,如下图:
循环引用不是循环调用,循环调用是方法之间的环调用,循环调用是无法解决的,除非有终结条件,否则出现死循环,最终导致内存溢出。
1)、Spring 如何解决循环依赖
Spring 容器循环依赖包括构造器循环依赖和 setter 循环依赖,那 Spring 容器如何解决循环依赖呢?先看下示例:
package com.luo.spring.guides.helloworld.beanloading.circulardependency;
import lombok.Data;
/**
* @author : archer
* @date : Created in 2022/11/7 19:30
* @description :
*/
@Data
public class TestA {
private TestB testB;
public void test(){
System.out.println("i am testA");
}
}
package com.luo.spring.guides.helloworld.beanloading.circulardependency;
import lombok.Data;
/**
* @author : archer
* @date : Created in 2022/11/7 19:31
* @description :
*/
@Data
public class TestB {
private TestC testC;
}
package com.luo.spring.guides.helloworld.beanloading.circulardependency;
import lombok.Data;
/**
* @author : archer
* @date : Created in 2022/11/7 19:31
* @description :
*/
@Data
public class TestC {
private TestA testA;
}
在 Spring 中将依赖循环的处理分成了 3 种情况。
1、构造器循环依赖
表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖。如在创建 TestA 类时,构造器需要 TestB,创建 TestB 就需要创建 TestC,而创建 TestC 又需要先创建 TestA,这样就形成了一个环,没办法创建。
Spring 容器将每一个正在创建的 bean 标识符放在一个 “当前创建 bean 池” 中,bean 标识符在创建过程中将一直保持在这个池子中,因此如果在创建 bean 过程中发现自己已经在 “当前创建 bean 池” 中时,将抛出 BeanCurrentlyInCreationException 异常,表示循环依赖;而对于创建完毕的 bean 将从 “当前创建 bean 池” 中被清除掉。
创建配置文件
<?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">
<bean id="testA" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestA">
<constructor-arg index="0" ref="testB"/>
</bean>
<bean id="testB" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestB">
<constructor-arg index="0" ref="testC"/>
</bean>
<bean id="testC" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestC">
<constructor-arg index="0" ref="testA"/>
</bean>
</beans>
创建测试用例
package com.luo.spring.guides.helloworld.beanloading.circulardependency;
import com.luo.spring.guides.helloworld.beanloading.factorybean.Car;
import com.luo.spring.guides.helloworld.beanloading.factorybean.CarFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author : archer
* @date : Created in 2022/11/7 19:56
* @description :
*/
public class Main {
public static void main(String[] args) {
try {
ApplicationContext bf = new ClassPathXmlApplicationContext("beanloading/circulardependency/circulardependency.xml");
((TestA)bf.getBean("testA")).test();
} catch (BeansException e) {
e.printStackTrace();
}
}
}
输出结果
分析
- Spring 容器创建 “testA” bean,首先去 “当前创建 bean 池” 查找是否当前 bean 正在创建,若没发现,则继续准备其需要的构造参数 “testB”,并将 “testA” 标识符放到 “当前创建 bean 池”。
- Spring 容器创建 “testB” bean,首先去 “当前创建 bean 池” 查找是否当前 bean 正在创建,若没发现,则继续准备其需要的构造参数 “testC”,并将 “testB” 标识符放到 “当前创建 bean 池”。
- Spring 容器创建 “testC” bean,首先去 “当前创建 bean 池” 查找是否当前 bean 正在创建,若没发现,则继续准备其需要的构造参数 “testA”,并将 “testC” 标识符放到 “当前创建 bean 池”。
- 到此为止 Spring 容器要去创建 “testA” bean,发现该 bean 标识符在 “当前创建 bean 池” 中,表示训话你来,抛出 BeanCurrentlyInCreationException 异常。
2、setter 循环依赖
表示通过 setter 注入方式构成的循环依赖。对于 setter 注入造成的依赖,是通过 Spring 容器提前暴露完成构造器注入,但未完成其他步骤(如 setter 注入)的 bean 来完成的。而且只能解决单例作用域的 bean 循环依赖。对于 singleton 作用域 bean,可以通过
setAllowCircularReferences(false)
来禁用循环引用。
它是通过提前暴露一个单例工厂方法,从而使其他 bean 能引用到该 bean,如下代码所示:
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
具体步骤如下:
- 1、Spring 容器创建单例 “testA” bean,首先根据无参构造器创建 bean,并暴露一个 ObjectFactory ,用于返回一个提前暴露的一个创建中的 bean,并将 “testA” 标识符放到 “当前创建 bean 池”,然后 setter 注入 “testB”。
- 2、Spring 容器创建单例 “testB” bean,首先根据无参构造器创建 bean,并暴露一个 ObjectFactory ,用于返回一个提前暴露的一个创建中的 bean,并将 “testB” 标识符放到 “当前创建 bean 池”,然后 setter 注入 “testC”。
- 2、Spring 容器创建单例 “testC” bean,首先根据无参构造器创建 bean,并暴露一个 ObjectFactory ,用于返回一个提前暴露的一个创建中的 bean,并将 “testC” 标识符放到 “当前创建 bean 池”,然后 setter 注入 “testA”,进行注入 “testA” 时,由于提前暴露了 ObjectFactory 工厂,从而使用它返回一个提前暴露的一个创建中的 bean。
- 4、最后再依赖注入 “testB” 和 “testA”,完成 setter 注入。
注意
:
SpringBoot 2.6.0
之后,Spring官方已经
不建议循环依赖
了,出现循环依赖还是最好从编码层面做解耦比较好,在此版本,以上代码在运行时会出现循环依赖,导致出现
java.lang.StackOverflowError
错误。
3、prototype 范围的依赖处理
对于 prototype 作用域的 bean,Spring 容器无法完成依赖注入,因为 Spring 容器不进行缓存 prototype 作用域的 bean,因此无法提前暴露一个创建中的 bean,示例如下:
创建配置文件
<?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">
<bean id="testA" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestA">
<property name="testB" ref="testB"/>
</bean>
<bean id="testB" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestB">
<property name="testC" ref="testC"/>
</bean>
<bean id="testC" class="com.luo.spring.guides.helloworld.beanloading.circulardependency.TestC">
<property name="testA" ref="testA"/>
</bean>
</beans>
测试
package com.luo.spring.guides.helloworld.beanloading.circulardependency;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author : archer
* @date : Created in 2022/11/7 19:56
* @description :
*/
public class Main {
//setter 注入 prototype 作用域
public static void main(String[] args) {
try {
ApplicationContext bf = new ClassPathXmlApplicationContext("beanloading/circulardependency/prototype/prototypecirculardependency.xml");
((TestA)bf.getBean("testA")).test();
} catch (BeansException e) {
e.printStackTrace();
}
}
}
输出
二、创建 bean
//给 BeanPostProcessors(后置处理器) 一个机会来返回代理(替代真正的实例)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
可以看出程序经历过 resolveBeforeInstantiation 方法后,如果创建了代理或者说重写了 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法,并在方法postProcessBeforeInstantiation 中改变了 bean,则直接返回,否则就进行常规 bean 的创建。代码如下:
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据指定 bean 使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
//应用 MergedBeanDefinitionPostProcessor
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//是否需要提早曝光:单例 & 允许循环依赖 & 当前 bean 正在创建中,来检查循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//为避免后期循环依赖,可在 bean 初始化完成前将创建实例的 ObjectFactory 加入工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//对 bean 进行填充,将各个属性值注入其中,若存在依赖于其他 bean 的属性,就会递归初始依赖 bean
populateBean(beanName, mbd, instanceWrapper);
//调用初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
if (earlySingletonReference != null) {
//如果 exposedObject 没有在初始化方法中被改变,即没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
//检测依赖
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//因为 bean 创建后其依赖的 bean 一定是已创建的,
//若 actualDependentBeans 不为空,则表示当期 bean 创建后所依赖的 bean 还没有全部创建完,也就是说存在依赖循环。
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
//根据 scope 注册 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
//对 bean 再一次依赖引用,主要应用 SmartInstantiationAwareBeanPostProcessor
//Aop 就是在这里将 advice 动态植入 bean 中,若没有则返回原本的 bean,不做任何处理
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
我们先来梳理下整个函数的概要思路(先忽略掉日志和异常)
- 1、如果是单例,则需要先清除缓存
-
2、实例化 bean,将 BeanDefinition 转换为 BeanWrapper
- a、如果存在工厂方法,则使用工厂方法进行初始化
- b、一个类有多个构造函数,每个构造函数都有不同的参数,所以苏姚根据参数锁定构造函数,并进行初始化
- c、如果即不存在工厂方法,也不存在带有参数的构造函数,则使用默认构造函数进行 bean 实例化
-
3、MergedBeanDefinitionPostProcessor 的应用
- bean 合并后的处理,Autowired 注解正是通过此方法实现诸如类型的预解析
-
4、依赖处理
- 解决循环依赖问题(只对单例有效)
- 5、属性填充,将所有属性填充至 bean 的实例中
-
6、循环依赖检查
- 对于 prototype 的 bean,Spring 没有好的解决办法,唯一要做的就是抛出异常,在这个步骤会检测已经加载的 bean 是否已经出现了循环依赖,并判断是否需要抛出异常
-
7、注册 DisposableBean
- 若配置了 destory-method,这里需要注册,以便于在销毁时调用
-
8、完成创建并返回
- 上面每一步骤都是用的大量的代码来完成其功能,最复杂的,同时也最难以理解的是循环依赖的处理
1、创建 bean 的实例
接下里我们来深入分析创建 bean 的每一个步骤,首先从 createBeanInstance 开始,代码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//解析 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//使用Supplier接口获取
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工厂方法不为空,则使用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//一个类有多个构造函数,每个构造函数都有不同的参数,
//所以调用前需要先根据参数锁定构造函数或对应的工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已经解析过,则使用解析好的构造函数方法,不需要再次锁定
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
//需要根据参数解析鼓噪函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
//若配置了首选构造函数,则使用它构造
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
//使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
下面简单梳理下逻辑:
- 1、如果在 RootBeanDefinition 中存在 InstanceSupplier 或者 FactoryMethodName 属性,或者在配置文件中配置了 factory-method ,那么 Spring 会尝试使用 obtainFromSupplier(instanceSupplier, beanName) 或 instantiateUsingFactoryMethod(beanName, mbd, args) 方法,根据 RootBeanDefinition 中的配置生成 bean 的实例。
- 2、解析构造函数,并进行构造函数的实例化。一个 bean 会有多个构造函数,Spring 会根据参数及类型去判断使用哪个构造函数来实例化。因为判断的过程是个比较消耗性能的工作,所以采用了缓存机制,如果已解析过,则直接从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则再次解析,并把结果缓存至 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中
1)、autowireConstructor
对于实例的创建,Spring 中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化由于存在不确定性,因此在判断对应参数上做了大量的工作。
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//explicitArgs 通过 getBean 方法传入
//如果 getBean 方法调用的时候指定方法参数,那么直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
//如果 getBean 方法调用的时候没有指定方法参数,则从配置文件中解析
Object[] argsToResolve = null;
//尝试从缓存中获取
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
//从缓存中取
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
//配置的构造函数参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//如果缓存中存在
if (argsToResolve != null) {
//解析参数类型,如给定方法的构造函数 A(int,int),
//则通过此方法后就会把配置中的 ("1","1") 转换为 (1,1)
//缓存中的值可能是原始值,也可能是最终值
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
//没有被缓存
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
//选取指定的(首选)构造函数
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
//不存在首选构造函数时,判断是否允许使用非 public 声明的构造函数,允许则获取所有,否则只获取 public 声明的构造函数
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
//只找到一个构造函数,则使用唯一的构造函数来实例化
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
//最小参数数(爱尔兰语单词)
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//提取配置文件中配置的构造函数参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//用于承载解析后的构造函数参数的值
resolvedValues = new ConstructorArgumentValues();
//能解析到的参数个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序给定的构造函数,按照 public 构造函数优先参数数量降序,非 public 构造函数参数数量降序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
//如果已经找到选用的构造函数,而且其需要的参数个数小于当前循环的构造函数参数个数,就终止
//因为已经按照数组是按照参数个数降序排列的
break;
}
if (parameterCount < minNrOfArgs) {
//参数个数不相等
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
//有参数则根据值构造对应参数类型的参数
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//获取指定构造函数的参数名称
paramNames = pnd.getParameterNames(candidate);
}
}
//根据名称和数据类型创建参数持有者
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
//明确参数的情况,参数必须精确匹配
if (parameterCount != explicitArgs.length) {
continue;
}
//构造函数没有参数的情况
argsHolder = new ArgumentsHolder(explicitArgs);
}
//探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 如果它代表当前最接近的匹配,则选择作为构造函数
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null && argsHolderToUse != null) {
//将解析的构造函数放入缓存
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
//将构造的实例加入到 beanwrapper 中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
//初始化 bean 的实例,使用指定的策略实例化 bean
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
//获取 bean 实例化的策略
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
函数总览:
-
1、构造函数参数的确定
- **1)、根据 explicitArgs 参数判断:**如果 explicitArgs 不为空,则直接确定参数,因为 explicitArgs 是用户调用 getBean 方法指定的。
// BeanFactory 中的方法
Object getBean(String name, Object… args) throws BeansException;
- **2)、缓存中获取:**若构造函数参数已经记录在缓存中,就可以直接拿来使用,缓存中缓存的可能是参数的最终类型,也可以是参数的初始类型,如构造函数需要的是 int 类型,但是原始的参数值是 String 类型的 “1”,所以这里需要经过类型转换器过滤,以确保参数类型与对应构造函数的参数类型完全对应。
- **3)、配置文件中获取:**前面的分析,我们已经得知,Spring 中的配置文件信息,最终会通过 BeanDefinition 实例承载,即参数 mbd 中包含,可以通过 mbd.getConstructorArgumentValues 来获取配置的构造函数信息。
-
2、构造函数的确定
- 经过第一步后,已经确定了构造函数的参数,接下来就是根据参数来确定对应的构造函数,而匹配的方法就是根据参数个数匹配,匹配之前对构造函数进行排序,这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件,还可以通过参数名称设定参数值,这种情况获取参数名称有两种方式,通过注解或使用 Spring 的工具类 ParameterNameDiscoverer 来获取。
-
3、根据确定的构造函数转换对应的参数类型
- 使用 Spring 中提供的类型转换器,或者用户提供的自定义类型转换器进行转换。代码在方法 createArgumentArray
-
4、构造函数不确定性的验证
- 不同构造函数的参数存在父子关系,所以 Spring 最后又做了一次验证。
-
5、根据实例化策略以及得到的构造函数即构造函数参数实例化 Bean
2)、instantiateBean
若没有使用带有参数的构造函数来实例化 Bean,就会使用默认的不带参数的构造函数来实例化。
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
无参构造函数实例化世界调用实例化策略实例化即可。Spring 主要把精力都放在了构造函数以及参数的匹配上。
3)、实例化策略
SimpleInstantiationStrategy.java
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
//如果有需要覆盖或者动态替换的方法,则需要使用 cglib 进行动态代理
//此时可以在创建代理的同时,将动态方法织入类中
//如果没有需要动态改变的方法,为了方便直接反射就可以了
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
CglibSubclassingInstantiationStrategy.java
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
- 若 bd.hasMethodOverrides() 为空,表示用户没有使用 replace 或 lookup 的配置方法,那么直接使用反射的方式创建实例。
- 若 bd.hasMethodOverrides() 不为空,表示用户使用了 使用 replace 或 lookup 的配置方法,则必须使用动态代理的方式,将包含两个特性的对应的逻辑的拦截器,增强并设置进去,返回值为包含拦截器的代理实例。
2、记录创建 bean 的 ObjectFactory
doCreateBean 函数中有如下代码:
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//为避免后期循环依赖,可以在 bean 初始化完成前,将创建实例的 ObjectFactory 加入工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
名词解释:
-
earlySingletonExposure
:字面理解是提早曝光的单例,看下有哪些条件影响这个值 -
mbd.isSingleton()
:代表此 RootBeanDefinition 代表的是否是单例 -
this.allowCircularReferences
: 是否允许循环依赖,在 AbstractRefreshableApplicationContext 中提供了设置函数,可以通过硬编码方式进行设置或者通过自定义命名空间进行配置,硬编码方式如下:
ClassPathXmlApplicationContext bf =
new ClassPathXmlApplicationContext("beanloading/circulardependency/prototype/prototypecirculardependency.xml");
bf.setAllowCircularReferences(false);
-
isSingletonCurrentlyInCreation(beanName):
该 bean 是否在创建中。Spring 中会有专门的属性 Set 类型默认为 DefaultSingletonBeanRegistry 的 singletonsCurrentlyInCreation 来记录 bean 的加载状态,在 bean 开始创建前会将 beanName 记录在属性中,创建结束后会将 beanName 从属性中移除,不同 scope 的记录位置并不一样,以 singleton 为例,在 singleton 下记录属性的函数是在 DefaultSingletonBeanRegistry#getSingleton 函数中的 beforeSingletonCreation(beanName) 和 afterSingletonCreation(beanName) 添加和移除的。
当 mbd.isSingleton()、this.allowCircularReferences 和 isSingletonCurrentlyInCreation(beanName) 三者都为 true 时,执行 addSingletonFactory 操作,那 addSingletonFactory 的作用是什么呢?
我们先以简单的 AB 循环依赖为例,类 A 中含有属性类 B,而类 B 中又会含有属性类 A,beanA 的初始化如下图:
其中解决循环依赖的关键在于创建 beanB 中的步骤 populateBean 方法中的 getBean(A) , 在这个方法中,并不是去直接实例化 A,而是先去缓存中查询是否存在已经创建好的对应的 bean,或者是已经创建好的 ObjectFactory,而对于 A 的 ObjectFactory 我们早已创建好,所以不会再往后执行,而是直接调用 ObjectFactory 来创建 A,这样就解决了循环依赖问题。
所以关键在于 ObjectFactory 的实现,我们来看下代码:
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
在 getEarlyBeanReference 函数中除了后处理器的调用,并没有太多的逻辑处理,根据以上分析,基本可看出 Spring 中处理循环依赖的解决办法,是在 B 中创建依赖 A 时,通过 ObjectFactory 提供的实例化方法来中断 A 中属性填充。使 B 中持有的 A 仅仅是刚刚初始化,并没有填充任何属性的 A,由于 A 与 B 中的属性 A 在内存中地址是一样的,所以 A 中创建好的属性填充,自然就可以通过 B 中的 A 获取。
3、属性注入
现在我们来了解下 populateBean 这个函数,它的主要功能是属性填充,那它是如何实现的呢?先来看下源码:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 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.
//给 InstantiationAwareBeanPostProcessors 最后一次机会在属性设置前来改变 bean
//如:可以用来支持属性注入的类型
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
//如果后处理器发出停止填充命令,则终止后续的执行
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
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;
}
//后处理器已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
//过滤描述类的属性值
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//对所有需要依赖检查的属性进行设置
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//一来检查,对应 depends-on 属性,3.0已经弃用此属性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//将属性应用到 bean 中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
populateBean 函数中的处理流程大致如下:
- 1、InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 函数的应用,此函数可以控制程序是否继续进行属性填充
- 2、根据注入类型(byName/byType),提取依赖的 bean,并统一存入 PropertyValues 中
- 3、应用 InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 函数。
- 4、将所有 PropertyValues 中的属性填充至 BeanWrapper 中。
接下来来分析一些功能的实现细节。
1)、autowireByName
- 在传入的参数 pvs 中找出已经加载的 bean,并递归实例化,进而加入到 pvs 中。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//寻找 bw 中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//递归初始化相关的 bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
2)、autowireByType
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//用于存储所有依赖的 bean,如果对于非集合类的属性注入,此属性毫无用处
//支持的是 @Autowired Private List<A> aList; 注入
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//寻找 bw 中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is an unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
//探测指定属性的 set 方法
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);
//解析指定 beanName 的属性所匹配的值,并把解析到的属性名称存储在
//autowiredBeanNames 中,当存在多个封装 bean 时,如:@Autowired Private List<A> aList;
//将会找到所有匹配 A 类型的 bean,并将其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//注册依赖
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);
}
}
}
DefaultListableBeanFactory.java
@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()) {
//ObjectFactory 类注入的特殊处理
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
//javaxInjectProviderClass 类注入的特殊处理
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//通用逻辑处理
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//用于支持 Spring 中新增的注解 @Value
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
//通过转换器将 bean 的值转换为对应的 type 类型
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//如果解析器没有成功解析,则需要考虑各种情况
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//根据属性类型找到 beanFactory 中所有类型的匹配 bean
//返回值的构成为:key=匹配的 beanName,value=beanName 对应的实例化后的 bean (通过 getBean(beanName) 返回)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
//如果 autowire 的require 属性为 true,而匹配项却为 null,则只能抛出异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), 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) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
3)、applyPropertyValues
程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以 PropertyValues 的形式存在的,要把属性应用到已经实例化的 bean 中的工作是在 applyPropertyValues 中完成的。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//如果 mpvs 中的值已经被转换为对应的类型,name可以直接设置到 beanWrapper 中
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
//如果 pvs 并不是使用 MutablePropertyValues 封装的类型,那么直接使用原始的属性获取方法
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//获取对应的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(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);
}
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);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
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();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
4、初始化 bean
init-method 的作用,是在 bean 实例化前,调用 init-method 指定的方法来根据用户业务进行相应的实例化。这个方法的执行位置是, Spring 中程序已经执行过 bean 的实例化,并且进行了属性的填充后,就会调用用户设定的初始化方法。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//应用后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//激活用户的自定义 init 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后处理器应用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
下面分步骤来分析上面函数的用作。
1)、激活 Aware 方法
Spring 提供了一些 Aware 相关接口,如: BeanFactoryAware、ApplicationContextAware,ResourceLoaderAware、ServletContextAware 等,实现这些 Aware 接口的 bean ,在初始化后,可以获取一些相对应的资源,如实现 BeanFactoryAware 的 bean 初始化后,Spring 容器将会注入 BeanFactory 的实例。先来看下 Aware 使用的示例。
a、定义普通 bean
package com.luo.spring.guides.helloworld.beanloading.aware;
/**
* @author : archer
* @date : Created in 2022/11/28 19:52
* @description :
*/
public class Hello {
public void say(){
System.out.println("hello");
}
}
b、定义 BeanFactoryAware 的 bean
package com.luo.spring.guides.helloworld.beanloading.aware;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
/**
* @author : archer
* @date : Created in 2022/11/28 19:53
* @description :
*/
public class Test implements BeanFactoryAware {
private BeanFactory beanFactory;
//声明 bean 的时候,Spring 会自动注入 beanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory=beanFactory;
}
public void testAware(){
Hello hello = (Hello) beanFactory.getBean("hello");
hello.say();
}
}
c、测试类运行测试
package com.luo.spring.guides.helloworld.beanloading.aware;
import com.luo.spring.guides.helloworld.beanloading.circulardependency.TestA;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author : archer
* @date : Created in 2022/11/28 19:55
* @description :
*/
public class Main {
public static void main(String[] args) {
try {
ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext("beanloading/aware/applicationContext.xml");
((Test)bf.getBean("test")).testAware();//输出 hello
} catch (BeansException e) {
e.printStackTrace();
}
}
}
<?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">
<bean id="hello" class="com.luo.spring.guides.helloworld.beanloading.aware.Hello"/>
<bean id="test" class="com.luo.spring.guides.helloworld.beanloading.aware.Test"/>
</beans>
我们来看下 Spring 的实现方式
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2)、处理器的应用
在调用用户自定义初始化方法前后,分别会调用 BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,让用户可以根据自己的业务需求进行相应式的处理。
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
3)、激活自定义的 init 方法
用户自定义的初始化方法除了 init-method 外,还有实现 InitializingBean 接口的自定义 bean,它里面的 afterPropertiesSet 中实现的初始化业务逻辑。
init-method 与 afterPropertiesSet 都是在初始化 bean 的时执行,执行顺序是先 afterPropertiesSet 后 init-method。
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//首先检查是否是 InitializingBean ,若是,则需要调用 afterPropertiesSet 方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//属性初始化后的处理
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
//调用自定义初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
5、注册 DisposableBean
Spring 还提供了销毁方法的扩展入口,对于销毁方法的拓展,我们可以使用 destroy-method 或者 DestructionAwareBeanPostProcessor 来处理。代码如下
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
//单例模式下注册需要销毁的 bean,此方法中会处理 DisposableBean 的 bean,
//并对所有的 bean 使用 DestructionAwareBeanPostProcessor 处理
//DisposableBean DestructionAwareBeanPostProcessors
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
//自定义 scope 的处理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}