文章目录
Spring中Bean的加载
接着上文Spring——4. Bean的加载(一),Spring中真正去加载bean的是doCreateBean()方法;这是一个非常复杂的过程,其中很难的一点就是对于循环依赖的处理,所以我们先来对循环依赖进行了解,然后再继续加载bean的解析。
1. Spring中的循环依赖
1.1 什么是循环依赖
循环依赖就是循环引用,两个或多个bean互相之间的持有对方,比如classA引用classB,
classB引用classC,classC又引用classA;最终成为一个环;
1.2 Spring中对于循环依赖的解决
Spring中的循环依赖包括:构造器循环依赖、setter循环依赖(singleton类型/prototype类型)。
首先定义三个互相引用的测试类:
public class ClassA {
private ClassB classB;
// 省略 构造器 及 set/get 方法
}
public class ClassB {
private ClassC classC;
// 省略 构造器 及 set/get 方法
}
public class ClassC {
private ClassA classA;
// 省略 构造器 及 set/get 方法
}
1.2.1 构造器循环依赖
表示通过构造器注入构成的循环依赖,这种依赖是无法解决的,只能抛出BeanCurrentlyInCreationException 异常表示循环依赖。
Spring容器会将每一个正在创建bean的beanName放在一个“当前创建bean池”(singletonsCurrentlyInCreation)中,这个beanName在bean的创建过程中将一直保持在这个池中。
如果在创建bean的过程中发现自己已经在这个池里的话,将会抛出 BeanCurrentlyInCreationException异常表示循环依赖;在bean创建完成的时候将beanName从这个池中移除。
实现代码:
DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 省略前面部分...
beforeSingletonCreation(beanName);
// 省略后面部分...
}
return singletonObject;
}
}
protected void beforeSingletonCreation(String beanName) {
// singletonsCurrentlyInCreation 是 Set<String> 类型的
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
使用示例:
- 使用上面定义的三个测试类ClassA、ClassB、ClassC;
- 创建一个配置文件:
constructor-circle-dependence-context.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA">
<constructor-arg name="classB" ref="classB"/>
</bean>
<bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB">
<constructor-arg index="0" ref="classC"/>
</bean>
<bean id="classC" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassC">
<constructor-arg index="0" ref="classA"/>
</bean>
</beans>
- 创建一个测试方法:
private static void byConstructor() {
try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:constructor-circle-dependence-context.xml");
} catch (Exception e) {
e.printStackTrace();
}
}
// output:
... nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'classA': Requested bean is currently in creation: Is there an unresolvable circular reference?
以上代码执行步骤:
- Spring容器创建“classA”的bean的时候,往singletonsCurrentlyInCreation中添加自己的beanName“classA”;然后继续构造自己依赖的“classB”的bean;
- Spring容器创建“classB”的bean的时候,往singletonsCurrentlyInCreation中添加自己的beanName“classB”;然后继续构造自己依赖的“classC”的bean;
- Spring容器创建“classC”的bean的时候,往singletonsCurrentlyInCreation中添加自己的beanName“classC”;然后继续构造自己依赖的“classA”的bean;
- Spring容器又会去创建“classA”的bean,但是在往singletonsCurrentlyInCreation中添加的时候,发现添加失败了也就是classA已经存在了,所以抛出异常;
所以可以看到最后抛出的BeanCurrentlyInCreationException异常;
1.2.2 setter循环依赖(singleton)
表示通过setter注入方式构成的循环依赖;对于setter造成的依赖是 通过Spring容器提前暴露
刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的(这里只能解决singleton类型的bean的循环依赖)。
通过提前暴露一个单例工厂方法,使得其他bean能够引用到该bean:
// earlySingletonExposure 是否需要提早曝光,条件:单例 & 允许循环依赖 & 当前bean正在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 如果需要提前曝光;
// 在bean初始化完成前将创建实例的 ObjectFactory 加入工厂
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);
}
}
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 对bean再一次依赖引用,主要应用 SmartInstantiationAwareBeanPostProcessor
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
使用示例:
- 使用上面定义的三个测试类ClassA、ClassB、ClassC;
- 创建一个配置文件:
setter-circle-dependence-context.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA">
<property name="classB" ref="classB"/>
</bean>
<bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB">
<property name="classC" ref="classC"/>
</bean>
<bean id="classC" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassC">
<property name="classA" ref="classA"/>
</bean>
</beans>
- 创建一个测试方法:
private static void bySetter() {
try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:setter-circle-dependence-context.xml");
} catch (Exception e) {
e.printStackTrace();
}
}
以上代码执行步骤:
- Spring容器创建“classA”的bean的时候,首先往singletonsCurrentlyInCreation中添加自己的beanName“classA”;
然后根据无参构造器创建一个“classA”的bean实例,并暴露一个 “ObjectFactory”的实例,用于返回一个提前暴露的 创建中的bean;然后继续setter注入自己依赖的“classB”的bean; - Spring容器创建“classB”的bean的时候,首先往singletonsCurrentlyInCreation中添加自己的beanName“classB”;
然后根据无参构造器创建一个“classB”的bean实例,并暴露一个 “ObjectFactory”的实例,用于返回一个提前暴露的 创建中的bean;然后继续setter注入自己依赖的“classC”的bean; - Spring容器创建“classC”的bean的时候,首先往singletonsCurrentlyInCreation中添加自己的beanName“classC”;
然后根据无参构造器创建一个“classC”的bean实例,并暴露一个 “ObjectFactory”的实例,用于返回一个提前暴露的 创建中的bean;然后继续setter注入自己依赖的“classA”的bean; - 然后在注入“classA”的时候,由于步骤1中已经提前暴露了“ObjectFactory”的实例,并且提供实现了ObjectFactory的getObject()方法,所以可以从这个getObject()方法的具体实现方法getEarlyBeanReference()中获取到暴露出来的正在创建中的“classA”的bean;(所以不需要再去对“classA”的bean进行注入,这样就不会发生循环依赖了)
- 然后再依次注入“classB”和“classA”的bean,完成setter注入;
1.2.3 setter循环依赖(prototype)
对于“prototype”作用域的bean,Spring容器无法完成依赖注入,因为Spring容器不进行缓存“prototype”作用域的bean,因此无法提前暴露一个创建中的bean。
使用示例:
- 使用上面定义的三个测试类ClassA、ClassB、ClassC;
- 创建一个配置文件:
prototype-circle-dependence-context.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA" scope="prototype">
<property name="classB" ref="classB"/>
</bean>
<bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB" scope="prototype">
<property name="classC" ref="classC"/>
</bean>
<bean id="classC" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassC" scope="prototype">
<property name="classA" ref="classA"/>
</bean>
</beans>
- 创建一个测试方法:
private static void byProtoType() {
try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:prototype-circle-dependence-context.xml");
System.out.println(applicationContext);
// 注意这里必须加 getBean() 才会触发 bean的创建,然后抛出异常
// 原因是在加载xml配置文件到BeanDefinition的时候,如果是singleton类型的,会提前去获取bean(DefaultListableBeanFactory#preInstantiateSingletons()方法中可看到)
System.out.println(applicationContext.getBean("classA"));
} catch (Exception e) {
e.printStackTrace();
}
}
// output:
... nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'classA': Requested bean is currently in creation: Is there an unresolvable circular reference?
以上代码的执行步骤跟setter方法注入singleton类型的bean差不多,只是不会提前暴露正在创建中的bean,所以也不会提供用于 获取提前暴露bean的ObjectFactory。
不同点是:
上文Spring——4. Bean的加载(一)的4.1 原型模式的依赖检查 中说到了“prototype”类型的bean在创建之前,会首先检查prototypesCurrentlyInCreation缓存中是否有对应的“beanName”,如果有则直接抛出异常:
AbstractBeanFactory.java#doGetBean()
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null && (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
并且在“prototype”类型的bean在执行真正创建的时候,也先往prototypesCurrentlyInCreation缓存中写入当前正在创建的beanName:
AbstractBeanFactory.java#doGetBean()
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
这里由于“classA”的prototype类型的bean,在它自己创建的时候已经添加到了prototypesCurrentlyInCreation缓存中,在“classC”的prototype类型的bean创建时候,需要依赖“classA”,再次去检查的时候,就发现这个缓存中已经有了,所以直接抛出了异常。
2. 真正创建bean(doCreateBean)
在了解了循环依赖的之后,继续来看上文Spring——4. Bean的加载(一)最后的真正创建bean;在经过了上文中 4.7.2 后处理器的应用 的resolveBeforeInstantiation()方法之后,如果没有返回改变或者生成的bean,就需要进行常规bean的创建了。
AbstractAutowireCapableBeanFactory.java#createBean()
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()) {
// 如果是单例,则先尝试从缓存中获取beanInstance,并清除缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 将 BeanDefinition转换成 BeanWrapper
// 实例化bean,根据指定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.
// 对于指定的bean,调用他们的 postProcessMergedBeanDefinition() 方法
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// bean合并后的处理,autowired注解通过此方法实现诸如类型的预解析
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.
// earlySingletonExposure 是否需要提早曝光,条件:单例 & 允许循环依赖 & 当前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 加入工厂
// AOP就是在这里将advice动态织入bean中
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);
if (earlySingletonReference != null) {
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);
}
}
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.
// Spring不但提供了对于初始化方法的扩展入口,统一提供了销毁方法的扩展入口;
// 对于销毁方法的扩展,除了配置 destroy-method方法外,还可以注册后处理器 DestructionAwareBeanPostProcessors来统一处理bean的销毁方法
try {
// 注册DisposableBean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
2.1 创建bean的实例
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析bean 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<?> 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) {
// 一个类有多个构造函数,每个构造函数有不同的参数,调用前需要先根据参数锁定构造函数或对应的工厂方法
// 采用“缓存机制”,如果已经解析过了就将解析的结果添加到 RootBeanDefinition的 resolvedConstructorOrFactoryMethod属性中;
// 不需要重复解析,直接从这个缓存中取;
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);
}
2.1.1 解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
这里在上文Spring——4. Bean的加载(一)的4.7 准备创建bean(createBean) 的第1小步中讲解了,就是根据beanName使用反射创建出类对象Class;由于前面已经创建过了,并设置到了BeanDefinition中,所以这里直接返回BeanDefinition中的beanClass即可:
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 如果 RootBeanDefinition中本身就有beanClass,就直接返回
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
}
......
}
2.1.2 处理Supplier
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
Supplier,是JDK1.8提供的一个函数式接口,用于为创建bean的实例指定一个回调,作为声明式指定的工厂方法的替代方法。表示结果的提供者,如果设置了这样的回调函数,它将覆盖任何其他构造函数或工厂方法元数据。
所以这里,如果获取到了设置的instanceSupplier,就使用这个设置的instanceSupplier去获取bean的实例;
2.1.3 处理factoryMethodName
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
如果在xml配置文件中配置了 factory-method属性,在读取配置文件的时候就会把这个属性对应的methodName写入到BeanDefinition的factoryMethodName属性中。
所以在这里,如果读取到了factoryMethodName属性,Spring就会尝试使用instantiateUsingFactoryMethod()方法根据BeanDefinition的配置去生成bean的实例。
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
2.1.4 解析构造函数
一个bean对应的类中可能会有多个构造函数,每个构造函数的参数都不同,Spring根据参数及类型会判断最终会使用哪个构造函数进行实例化。
但是这个判断的过程比较复杂也比较缓慢,所以采用了缓存机制,将解析过的结果添加到 resolvedConstructorOrFactoryMethod缓存中。
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 采用“缓存机制”,如果已经解析过了就将解析的结果添加到 RootBeanDefinition的 resolvedConstructorOrFactoryMethod属性中;
// 不需要重复解析,直接从这个缓存中取;
if (mbd.resolvedConstructorOrFactoryMethod != null) {
// 不为空,说明已经解析过了
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
所以这里直接判断是否已经解析过了,如果解析过了直接把相关字段设置为true;并且使用解析好的构造函数创建bean的实例,而不是需要再次去解析。对于bean实例的创建Spring分为了两种情况:一种是默认构造函数的实例化,一种是带有参数的构造函数的自动注入实例化。
if (resolved) {
// 如果已经解析过了,则使用解析好的构造函数方法
if (autowireNecessary) {
// 构造函数自动注入(带有参数的实例化),非常复杂(主要复杂在构造函数及参数的匹配上)
return autowireConstructor(beanName, mbd, null, null);
} else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
2.1.4.1 autowireConstructor
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
ConstructorResolver.java
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方法传入;Object getBean(String name, Object... args)
// 如果传入参数explicitArgs不为空,则可以确定构造函数参数就是它;
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, true);
}
}
// 如果没有被缓存,且没有指定方法参数,就从配置文件中解析
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
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();
// 有了配置的参数信息,就可以获取对应的参数值信息(使用resolveConstructorArguments处理),并返回解析到的参数的个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 排序给定的构造函数(排序算法:1. public构造函数优先;2. 参数数量降序)
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<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 {
// 由于在配置文件中并不是限制只能使用参数索引的方式去创建,还支持指定参数名称进行设定参数值;如 <constructor-arg name="classB" ref="classB"/>
// 所以这种情况下,就需要首先确定构造函数中的参数名称;获取参数名称有两种方式:注解、ParameterNameDiscoverer
// 通过注解获取参数名称
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 LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// 构造函数没有参数的情况,直接使用getBean方法指定的参数,创建参数持有者
// 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 " +
"(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 in bean '" + beanName + "' " +
"(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");
// 根据实例化策略,以及得到的 构造函数 和 构造函数参数 实例化bean;
Object beanInstance = instantiate(beanName, mbd, constructorToUse, argsToUse);
bw.setBeanInstance(beanInstance);
return bw;
}
这个方法逻辑很复杂,代码量也很大,感觉不太符合Spring一贯的编码风格…下面就来一步一步地分析这个方法中的内容:
- 构造函数参数的确定:
-
根据explicitArgs判断:
// explicitArgs是通过getBean方法传入;Object getBean(String name, Object... args) // 如果传入参数explicitArgs不为空,则可以确定构造函数参数就是它; if (explicitArgs != null) { argsToUse = explicitArgs; }
如果getBean时传入的参数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) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); } }
如果没有传入explicitArgs参数,则先尝试从缓存中去获取参数;这里有个区别就是解析完成的构造器参数和解析了部分的构造器参数。
因为在缓存中缓存的可能是参数的最终类型(解析完成的),也可能是参数的初始类型,例如:构造函数要求的是int类型,但是初始类型是String。所以需要经过类型转换器的过滤以确保参数类型和构造函数参数类型对应。
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve, boolean fallback) { TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); TypeConverter converter = (customConverter != null ? customConverter : bw); BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); Class<?>[] paramTypes = executable.getParameterTypes(); Object[] resolvedArgs = new Object[argsToResolve.length]; for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) { Object argValue = argsToResolve[argIndex]; MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex); if (argValue == autowiredArgumentMarker) { argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback); } else if (argValue instanceof BeanMetadataElement) { argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue); } else if (argValue instanceof String) { argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd); } Class<?> paramType = paramTypes[argIndex]; try { resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam); } catch (TypeMismatchException ex) { throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage()); } } return resolvedArgs; }
-
从配置文件中获取:
如果没有传入explicitArgs参数也无法在缓存中获取到参数,就只有从配置文件中获取配置的构造函数的参数了。
经过之前的分析,我们知道了Spring中的配置文件的信息都会被封装到BeanDefinition的实例中,也就是参数mbd中;所以我们可以通过 mbd.getConstructorArgumentValues()方法获取到配置文件中的信息,有了配置文件中的信息,就可以获取到参数值的信息,并且获取解析到的参数的个数:// 获取配置文件中的配置的构造函数参数信息 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); // 用于承载解析后的,构造函数参数的值 resolvedValues = new ConstructorArgumentValues(); // 有了配置的参数信息,就可以获取对应的参数值信息(使用resolveConstructorArguments处理),并返回解析到的参数的个数 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
只是这个部分放在了下面和 构造函数的确定 一起了。
-
- 构造函数的确定(当构造函数为空,或者构造函数参数为空):
- 判断是否有传过来的构造函数,如果没有传过来就进行处理:
如果没有传过来就从BeanDefinition的beanClass对象中去获取;// Take specified constructors, if any. Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { 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); } }
- 可能是默认构造函数的处理:
如果构造函数只有一个;并且没有构造函数参数;也没有构造函数参数的值,说明就是只有一个默认的构造函数,则可以直接进行 instantiate实例化bean。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; } }
- 确定构造函数参数,及参数的最小个数:
如果传过来了构造函数参数,则最小的参数个数肯定是传过来的参数个数;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(); // 有了配置的参数信息,就可以获取对应的参数值信息(使用resolveConstructorArguments处理),并返回解析到的参数的个数 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); }
如果没有传过来,并且到了这个步骤的肯定是没有从缓存中获取到构造函数参数的;所以这里就去配置文件中读取配置的构造函数参数的信息;读取到后进行解析构造函数参数并封装到 resolvedValues中,并且返回参数的最小个数。 - 确定构造函数:
在已经确定了构造函数参数之后,接下来就应该根据构造函数参数在所有的构造函数中锁定对应的构造函数。
匹配的方法就是根据参数个数进行匹配,所以在匹配之前需要先对构造函数进行排序,排序规则:public优先,参数数量降序;非public其次,参数数量降序。
由于在配置文件中并不是唯一限制使用参数位置索引去创建构造器参数,还支持使用指定参数名称的方式,所以需要首先确定构造函数中参数名称;这里就需要进行转换响应的参数类型:AutowireUtils.sortConstructors(candidates);
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 { // 由于在配置文件中并不是限制只能使用参数索引的方式去创建,还支持指定参数名称进行设定参数值;如 <constructor-arg name="classB" ref="classB"/> // 所以这种情况下,就需要首先确定构造函数中的参数名称;获取参数名称有两种方式:注解、ParameterNameDiscoverer // 通过注解获取参数名称 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 LinkedList<>(); } causes.add(ex); continue; } } else { // 构造函数没有参数的情况,直接使用getBean方法指定的参数,创建参数持有者 // 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); } }
- 判断是否有传过来的构造函数,如果没有传过来就进行处理:
- 根据实例化策略以及得到的构造函数及构造函数参数实例化bean:
这里的根据策略实例化bean后面一点再解析。// 根据实例化策略,以及得到的 构造函数 和 构造函数参数 实例化bean; Object beanInstance = instantiate(beanName, mbd, constructorToUse, argsToUse); bw.setBeanInstance(beanInstance); private Object instantiate( String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) { try { 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); } }
2.1.4.2 instantiateBean
经历了带参数的构造函数的实例化,再来看不带参数的构造函数的实例化过程应该会觉得很简单了:
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);
}
}
因为带参数的构造函数的实例化过程中,主要精力都是放在了构造函数参数以及构造函数的确定上;所以没有参数的实例化过程,就是直接根据实例化策略进行实例化就行了。
2.1.4.3 不同实例化策略 -> 实例化bean
其实经过前面的解析,已经得到了足够实例化的所有相关信息,完全可以使用最简单的反射就可以构造实例对象;但是为什么Spring为什么要采用不同的实例化策略来构造对象呢?
InstantiationStrategy.java
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) throws BeansException;
SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果没有覆盖或者动态替换的方法,直接使用反射
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);
}
// 如果有需要覆盖或者动态替换的方法,需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}
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())成立,也就是没有使用lookup-method或者replace-method方法,那么直接使用反射的方式就可以构造实例对象了;
- 如果使用了这两个特性,就需要将这两个配置提供的功能切入进去,所以必须要用到动态代理的方式将包含两个特性所对应的逻辑的 拦截增强器设置进去,这样才可以保证在调用方法的时候会被响应的拦截器增强,返回值会包含拦截器的代理实例。
2.2 依赖处理
在获取到bean实例之后,首先会将MergedBeanDefinitionPostProcessors应用到指定的bean定义上(主要是调用它们的postProcessMergedBeanDefinition()方法)。然后就该对于bean的依赖进行处理了,也就是Spring中循环依赖的解决。
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 加入工厂
// AOP就是在这里将advice动态织入bean中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
- earlySingletonExposure:是否是单例、是否允许循环依赖、是否对应的bean正在创建;三个条件的综合,当这三个条件都满足时,才会执行addSingletonFactory操作;
- allowCircularReferences:并没有在配置文件中找到如果配置这个属性,不过可以通过获取ApplicationContext的时候进行设置:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:setter-circle-dependence-context.xml"); applicationContext.setAllowCircularReferences(false);
- isSingletonCurrentlyInCreation(beanName):当前bean是否在创建中;
- Spring中使用了 DefaultSingletonBeanRegistry的 singletonsCurrentlyInCreation属性来记录bean的加载状态;
- 在bean创建之前会将beanName记录在这个属性中,在bean创建结束后会将beanName从属性中移除;
在上文Spring——4. Bean的加载(一)的 4.6.1 singleton类型bean的创建 中:- bean创建之前,调用了 beforeSingletonCreation(beanName)方法,记录了当前beanName正在创建的状态到 singletonsCurrentlyInCreation属性中:
beforeSingletonCreation(beanName); protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
- bean创建之后(在当前整个createBean()完成之后),调用了 afterSingletonCreation(beanName)方法,移除记录在 singletonsCurrentlyInCreation属性中的beanName:
afterSingletonCreation(beanName); protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
- bean创建之前,调用了 beforeSingletonCreation(beanName)方法,记录了当前beanName正在创建的状态到 singletonsCurrentlyInCreation属性中:
示例:
以简单的AB循环依赖为例,类A中含有属性类B,类B中又会含有属性类A;Spring对这种情况下的循环依赖处理如下:
里面相关方法的具体实现代码在上面文章中都能找到,结合起来应该就能看明白了,这也就是Spring解决循环依赖的具体实现。
2.3 属性注入
在上面说到的解决循环依赖的过程中已经提到了填充属性,也就是populateBean()方法:
AbstractAutowireCapableBeanFactory.java
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;
}
}
// 给 InstantiationAwareBeanPostProcessors 最后一次机会在属性设置前来改变bean的状态;
// 如:可以用来支持属性注入的类型
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// BeanDefinition不是自定义的,并且已经注册了 InstantiationAwareBeanPostProcessors
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
// postProcessAfterInstantiation 可以控制是否继续进行属性填充
if (!ibp.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);
}
// 提取依赖的bean,并统一存入 PropertyValues
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 (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;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 依赖检查,对应depends-on属性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 将所有PropertyValues中的属性填充至 BeanWrapper中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
主要步骤:
- 如果注册了 InstantiationAwareBeanPostProcessors,则应用 InstantiationAwareBeanPostProcessor处理的 postProcessAfterInstantiation()方法,控制程序是否还要继续属性填充;
- 根据不同的注入类型(byName/byType)进行注入,并且提取依赖的bean,并统一存入 PropertyValues;
- 如果注册了 InstantiationAwareBeanPostProcessors,则应用 InstantiationAwareBeanPostProcessor处理的 postProcessProperties()方法,对属性获取完毕填充前对属性的再次处理;(典型应用是 RequiredAnnotationBeanPostProcessor 类中对属性的验证)
- 如果需要依赖检查的话,进行依赖检查;
- 将所有PropertyValues中的属性填充至 BeanWrapper中;
这里重点讲一下依赖注入及属性填充,在讲依赖注入之前,先讲讲Spring中自动装配(autowire)的几种模式。
2.3.1 autowire
在Spring中,autowire有5中模式:
- no(默认):
对应源码的 int AUTOWIRE_NO = 0; Spring默认的是不进行自动装配,通过手工设置ref来进行装配bean;示例:<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA"> <property name="classB" ref="classB"/> </bean> <bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB"> <property name="classC" ref="classC"/> </bean>
- byName:
对应源码的 int AUTOWIRE_BY_NAME = 1; 通过参数的名字进行装配bean;如果当前bean要装配的bean的property 和另外一个bean的name相同,就进行装配;示例:<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA" autowire="byName"> </bean> <bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB" autowire="byName"> </bean>
- byType:
对应源码的 int AUTOWIRE_BY_TYPE = 2; 通过参数的数据类型进行装配bean;如果当前bean要装配的bean的数据类型和另外一个bean的相同,就进行装配;示例:<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA" autowire="byType"> </bean> <bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB" autowire="byType"> </bean>
- construct:
对应源码的 int AUTOWIRE_CONSTRUCTOR = 3; 构造方法的参数通过byType的形式自动装配;示例:<bean id="classA" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassA" autowire="constructor"> </bean> <bean id="classB" class="org.bgy.spring.study.spring.bean.definition.circle.dependence.ClassB" autowire="constructor"> </bean>
- default:
由上级标签的default-autowire属性确定;
2.3.2 autowireByName
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
// 根据名称自动注入
autowireByName(beanName, mbd, bw, newPvs);
}
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);
// 加入到PropertyValues中
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");
}
}
}
}
这里首先获取到当前bean中需要依赖注入的属性propertyNames,并且遍历这个propertyNames判断每个propertyName,如果包含了bean,就递归初始化这个需要依赖的bean;最后再加入到 PropertyValues中。
2.3.3 autowireByType
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// 根据类型自定注入
autowireByType(beanName, mbd, bw, newPvs);
}
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 获取需要依赖注入的属性
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 a 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将将其注入
// resolveDependency 寻找类型匹配的逻辑
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 加入到PropertyValues中
pvs.add(propertyName, autowiredArgument);
}
// 新建了局部遍历 autowiredBeanNames,用于存储所有依赖的bean(如果只是对非集合类的属性注入,这里无效)
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);
}
}
}
这里首先获取到当前bean中需要依赖注入的属性propertyNames,并且遍历这个propertyNames的每一个propertyName:
- 把这个propertyName转换成PropertyDescriptor的实例pd,这个实例中会包含:当前bean的Class类型 和property属性的type、set/get方法、name等;
- 从pd中获取到需要注入的property属性的set方法的MethodParameter的实例 methodParam;
- 获取优先级eager,并且使用 methodParam和eager一起生成 DependencyDescriptor的实例desc;
- 寻找类型匹配的bean;
- 最后再加入到 PropertyValues中;
这里最复杂的就是寻找类型匹配的bean:
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
DefaultListableBeanFactory.java
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()) {
// Optional 类注入的特殊处理
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;
}
}
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();
// 用于支持注解 @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 {
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()));
}
}
// 如果解析器没有解析成功,需要考虑各种情况
// 解析多个bean
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()) {
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);
}
}
这里的resolveCandidate()方法,会去递归调用beanFactory的getBean()方法初始化依赖的bean:
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
也就跟前面的autowireByName()方法的这里一样。
2.3.4 applyPropertyValues
程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以PropertyValues形式存在的,还没有应用到已经实例化的bean中,应用的工作是在applyPropertyValues()方法中:
if (pvs != null) {
// 将所有PropertyValues中的属性填充至 BeanWrapper中
applyPropertyValues(beanName, mbd, bw, pvs);
}
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中的值已经被转换为对应的类型,那么可以直接设置到beanWrapper中;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
// 把属性应用到beanWrapper中
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 {
// 处理完成后,把属性应用到beanWrapper中
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
2.4 初始化bean
在前面,我们已经做了对bean的实例化,并且进行了属性的填充;这个时候,才会对bean进行初始化,代码实现:
exposedObject = initializeBean(beanName, exposedObject, mbd);
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()) {
// 用户对Spring的扩展的地方
// 在调用自定义初始化方法前,调用 BeanPostProcessor 的 postProcessBeforeInitialization() 方法,对业务需求进行相应的处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 用户自定义的初始化方法有两种:
// 1. 配置 init-method 方法;
// 2. 使自定义的bean 实现 InitializingBean接口,并在 afterPropertiesSet() 中实现自己的初始化业务逻辑
// 调用用户自定义的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()) {
// 在调用自定义初始化方法后,调用 BeanPostProcessor 的 postProcessAfterInitialization() 方法,对业务需求进行相应的处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在初始化bean的过程中,有以下几个主要步骤:
2.4.1 调用 Aware方法
在分析源码之前,先来了解一下Aware接口的使用。
Spring中提供了很多Aware接口,比如:BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等。
作用:实现了这些Aware接口的bean,在被初始化之后,会被注入一些相对应的资源;比如:实现了BeanFactoryAware的bean在被初始化之后,Spring容器将会注入BeanFactory的实例;实现了ApplicationContextAware的bean在被初始化之后会,Spring容器将会注入ApplicationContext的实例等。
示例代码:
- 先创建一个普通的bean:
public class Hello {
public void say() {
System.out.println("hello");
}
}
- 创建一个实现了Aware接口的 BeanFactoryAwareDemo的bean:
public class BeanFactoryAwareDemo implements BeanFactoryAware {
private BeanFactory beanFactory;
/**
* 声明bean的时候,Spring会自动注入BeanFactory
* @param beanFactory
* @throws BeansException
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void testAware() {
// 这里使用Spring主动注入的beanFactory来获取hello的bean
Hello hello = (Hello)beanFactory.getBean("hello");
hello.say();
}
}
- 创建xml配置文件:
aware-context.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="org.bgy.spring.study.spring.bean.definition.aware.Hello"/>
<bean id="beanFactoryAwareDemo" class="org.bgy.spring.study.spring.bean.definition.aware.BeanFactoryAwareDemo"/>
</beans>
- 创建一个测试类:
public class BeanFactoryAwareTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:aware-context.xml");
BeanFactoryAwareDemo beanFactoryAwareDemo = (BeanFactoryAwareDemo)applicationContext.getBean("beanFactoryAwareDemo");
beanFactoryAwareDemo.testAware();
}
}
// output:
hello
回到代码:
invokeAwareMethods(beanName, bean);
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);
}
}
}
代码主要就是对于不同的Aware类型,设置不同的属性值(资源)。
2.4.2 后置处理器的应用
2.4.2.1 BeanPostProcessor
BeanPostProcessor是Spring开放式架构中必不可少的一个亮点,可以给用户充足的权限去更改或者扩展Spring。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
postProcessBeforeInitialization()执行时机:实例化方法执行之后,init()方法执行之前;
postProcessAfterInitialization() 执行时机:init()方法执行之后;
这里返回的都是bean;
作用:
通过实现这个接口,用户可以对Spring管理的bean在初始化之前或者初始化之后,实现一些自定义的逻辑处理;其实也就是对Bean的一种增强。
回到代码,对于BeanPostProcessor的注册是在其他地方完成的,这里其实就是应用 BeanPostProcessor的地方了:
- 在调用用户自定义初始化方法前会调用postProcessBeforeInitialization()方法:
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
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;
}
- 在调用用户自定义初始化方法后会调用postProcessAfterInitialization()方法:
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
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;
}
这两个地方返回的都是调用了 BeanPostProcessor接口的两个方法之后,被增强了的wrappedBean。
2.4.3 调用自定义的初始化方法
在bean的配置中,有一个 init-method 的属性;这个属性的作用是在bean加载完成之前,调用init-method指定的方法来根据用户业务指定的初始化方法对bean进行相应的初始化。
用户自定义的初始化方法除了使用配置的 init-method之外,还可以使用自定义的bean实现 InitializingBean接口,并在 afterPropertiesSet()方法中实现自己的初始化逻辑。
init-method和 afterPropertiesSet都是在初始化bean时调用 invokeInitMethods()方法的时候执行的,执行顺序是 afterPropertiesSet先执行,init-method后执行。
invokeInitMethods(beanName, wrappedBean, mbd);
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
// 如果是 InitializingBean,就需要调用 afterPropertiesSet()方法
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("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 {
// 调用afterPropertiesSet
((InitializingBean)bean).afterPropertiesSet();
}
}
// 不是 InitializingBean
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用自定义初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
在这里,如果不是 InitializingBean,即是init-method方法,就调用自定义方法进行初始化:
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Could not find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
} else {
if (logger.isTraceEnabled()) {
logger.trace("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>)() -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
} catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException)pae.getException();
throw ex.getTargetException();
}
} else {
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
这个实现也比较简单,先从RootBeanDefinition中获取到 init-method中的指定的初始化方法的名称 initMethodName,然后使用反射获取到方法的Method,再使用反射调用就行了。
2.5 再次检查循环依赖
在这里会再次检测已经加载的bean是否已经出现了循环依赖,并判断是否需要抛出异常(但是我自己经过调试,好像没有找到什么情况会走到这一步才检测出来循环依赖的…):
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
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);
}
}
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.");
}
}
}
}
2.6 注册DisposableBean
Spring中不但提供了对于初始化方法的扩展入口,还提供了对于销毁方法的扩展入口;对于销毁方法的扩展,除了xml的配置属性 destroy-method之外,还可以通过注册后处理器 DestructionAwareBeanPostProcessor来统一处理bean的销毁方法:
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使用 DestructionAwareBeanPostProcessors处理
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 自定义 scope的处理
// A bean with a custom 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, getBeanPostProcessors(), acc));
}
}
}
在这里首先判断是否需要进行自定义销毁bean:
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
判断需要销毁成立的主要条件是:指定了destroy-method方法,或者注册了 DestructionAwareBeanPostProcessor后处理器。
在判断到需要自定义销毁bean之后,就根据bean的不同模式进行处理。
到这里,Spring中bean的加载流程就分析完毕了。
3. 整体流程思维导图
最后附上一个整体流程的思维导图:Spring Bean加载体系。