由于掘金文章存在字数限制,本文拆开了各个章节分开发布,全文可点击以下链接进行阅读:blog.omghaowan.com/archives/sp…
在Spring中,对Bean的实例化是在使用BeanFactory#getBean方法获取bean时完成的。在实现上,BeanFactory会委托于AbstractBeanFactory#doGetBean进一步处理:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
*/
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// transformedBeanName方法的转换主要应用于FactoryBean,
// 在实现上它会去除name中所有的&前缀并赋值给beanName
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Check if bean exists circular reference.
// ...
// Check if bean definition exists in this factory.
// ...
// ...
// 经过此步骤的BeanDefinition可被称之为MergedBeanDefinition
// 将给定的bean转化为RootBeanDefinition,当bean定义存在继承关系则会合并它的parent并返回RootBeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // getMergedBeanDefinition方法用于处理bean的继承特性,
// 检查bean定义是否抽象
// ...
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
// 假设dependsOn不为空
for (String dep : dependsOn) {
// 检查是否有循环依赖
...
// 实例化依赖
getBean(dep);
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
// 假设没有异常
return createBean(beanName, mbd, args);
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = createBean(beanName, mbd, args);
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 假设scopeName是有效的
String scopeName = mbd.getScope();
// 假设scope存在
Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, () -> {
// 假设没有异常
return createBean(beanName, mbd, args);
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
}
在AbstractBeanFactory#doGetBean中,首先会在单例作用域缓存中检测是否存在请求的bean实例,如果存在会直接从缓存中获取;否则会按照下列步骤对其进行创建:
- 获取/创建
MergedBeanDefinition - 获取/创建
depends-on指定的bean - 获取/创建
MergedBeanDefinition对应的bean - 获取/创建
bean中真正的实例对象 - 适配/转换
bean为目标的实例类型
MergedBeanDefinition(逻辑概念),表示的是一种被合并出来的BeanDefinition,其主要作用是处理存在继承关系的bean定义(BeanDefinition)。在AbstractBeanFactory#doGetBean中,Spring会直接通过getMergedLocalBeanDefinition方法来获取最终已处理完继承逻辑的BeanDefinition(若有继承关系,即MergedBeanDefinition);在实现上,getMergedLocalBeanDefinition方法会根据原始的BeanDefinition及其父BeanDefinition(如有)生成对应的副本,并最终返回RootBeanDefinition(也正因如此,Spring将这种合并出来的BeanDefinition称为MergedBeanDefinition(逻辑概念))。
我们可以看到无论是单例作用域还是其它类型的作用域(含prototype作用域)它们都会在作用域缓存中获取实例失败后使用AbstractBeanFactory#createBean方法对bean进行实例化。其中,AbstractBeanFactory#createBean方法为抽象方法,它的默认实现为AbstractAutowireCapableBeanFactory#createBean。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
/**
* Create a bean instance for the given merged bean definition (and arguments).
* The bean definition will already have been merged with the parent definition
* in case of a child definition.
* <p>All bean retrieval methods delegate to this method for actual bean creation.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
*/
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;
}
/**
* ...
*
* <p>Provides bean creation (with constructor resolution), property population,
* wiring (including autowiring), and initialization. Handles runtime bean
* references, resolves managed collections, calls initialization methods, etc.
* Supports autowiring constructors, properties by name, and properties by type.
*
* ...
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//...
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper 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.
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// To resolve circular references
// ...
// Initialize the bean instance.
populateBean(beanName, mbd, instanceWrapper);
Object exposedObject = initializeBean(beanName, bean, mbd);
// To resolve circular references
// ...
// Register bean as disposable.
// ...
return exposedObject;
}
}
前置知识:
为了更充分的理解
bean的实例化过程,在分析AbstractBeanFactory#createBean方法前,我们先来看一下Spring在bean的实例化过程存在的一些扩展点,具体如下所述:
BeanPostProcessor
BeanPostProcessor的语义中允许我们可以在bean执行初始化(initialization)前后对bean进行前置处理(BeanPostProcessor#postProcessBeforeInitialization)和后置处理(进行前置处理(BeanPostProcessor#postProcessAfterInitialization)。一般情况下(典型),我们可以在前置处理中对bean实例进行属性的填充;而在后置处理中对bean实例进行代理的封装。
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor是BeanPostProcessor的扩展子接口,它在BeanPostProcessor语义的基础上新增了对bean实例化(instantiation)前后的扩展点,即实例化前置处理(InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation)和实例化后置处理(InstantiationAwareBeanPostProcessor#postProcessProperties),其中实例化的后置处理会发生在显式属性设置(applyPropertyValues)前。一般情况下(典型),我们可以在前置处理中阻止特定bean执行默认的实例化流程,例如对特定bean(比如,延迟初始化的bean)以代理的方式进行创建;而在后置处理中我们可以对bean实例实现额外的注入策略,例如字段注入。除此之外,InstantiationAwareBeanPostProcessor还提供了InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation扩展点让我们可以控制bean是否能执行字段的自动注入(已通过构造器或者工厂方法完成实例化)。
SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor是InstantiationAwareBeanPostProcessor的扩展子接口,它在InstantiationAwareBeanPostProcessor语义的基础上新增了更多可以干预bean的扩展点,具体如下所示:
扩展点 具体作用 predictBeanType预测最终从 postProcessBeforeInstantiation返回的bean类型,可用于判断出某些特定的进行处理。determineCandidateConstructors决定给定 bean可以使用的候选构造器,可用于决定bean在实例化时所使用的构造器。getEarlyBeanReference获取特定 bean早期的访问引用(即在bean实例完全初始化前提前获取),专用于解决循环依赖问题。一般情况下,对于
getEarlyBeanReference方法所返回的实例应该与BeanPostProcessor#postProcessBeforeInitialization和BeanPostProcessor#postProcessAfterInitialization所返回的实例相等(引用)。
DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor是BeanPostProcessor的扩展子接口,它在BeanPostProcessor语义的基础上新增了对bean销毁前的扩展点,即销毁前置处理(DestructionAwareBeanPostProcessor#postProcessBeforeDestruction)。一般情况下(典型),我们可以在前置处理中对bean执行销毁回调,例如上文所提及的DisposableBean#destroy方法和通过其它方式自定义的销毁方法。另外,DestructionAwareBeanPostProcessor还提供了DestructionAwareBeanPostProcessor#requiresDestruction扩展点,通过它我们可以决定给定的bean实例是否执行DestructionAwareBeanPostProcessor的销毁前置处理。
MergedBeanDefinitionPostProcessor
MergedBeanDefinitionPostProcessor是BeanPostProcessor的扩展子接口,它在BeanPostProcessor语义的基础上新增了对合并的bean定义(MergedBeanDefinition)属性设置前的扩展点,即属性设置前置处理(MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition)。一般情况下(典型),我们可以通过MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition在bean实例的后置处理器前准备一些元数据的缓存;或者在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法中执行对bean定义属性的修改。
MergedBeanDefinition概念源自bean继承特性的处理,实际上MergedBeanDefinition只是一个逻辑概念,本质上还是一个RootBeanDefinition,我们可以简单地将它看作是原始bean定义的副本。由于在实例化过程中也涵盖了bean继承特性的处理(在AbstractBeanFactory#doGetBean实现中使用getMergedLocalBeanDefinition方法获取最终RootBeanDefinition时,如果存在bean定义的继承关系则会处理父定义属性的继承),所以在最终用于创建bean实例的BeanDefinition也属于MergedBeanDefinition。综上所述,在结合
Spring提供的(上述提及的)各个扩展点后,最终执行流程如下所示:+------------------------------------------+ | InstantiationAwareBeanPostProcessor | | +----------------------------------+ | | | postProcessBeforeInstantiation | | | +----------------------------------+ | | +--------------------------------------+ | | | MergedBeanDefinitionPostProcessor | | | | +---------------+ | | | | | Instantiation | | | | | +---------------+ | | | | +----------------------------------+ | | | | | postProcessMergedBeanDefinition | | | | | +----------------------------------+ | | | +--------------------------------------+ | | +----------------------------------+ | | | postProcessProperties | | | +----------------------------------+ | +------------------------------------------+ | v +-------+-------+ | populateBean | +-------+-------+ | v +------------------+-------------------+ | BeanPostProcessor | | +----------------------------------+ | | | postProcessBeforeInitialization | | | +----------------------------------+ | | +---------------+ | | |Initialization | | | +---------------+ | | +----------------------------------+ | | | postProcessAfterInitialization | | | +----------------------------------+ | +--------------------------------------+更多关于上述扩展点的详情可阅读以下资料:
对于bean的创建,我们可以将它大致分为bean的实例化和bean的初始化,其中bean的实例化主要包括bean实例创建、bean属性加载和bean属性填充3个部分;而bean的初始化则是执行用户预设的初始化方法。下面我们将分点进行阐述:
除了使用预设的步骤创建
bean实例,我们还可以通过Spring提供的扩展点来自定义bean的创建步骤。具体地,Spring在创建bean实例前会提供了一个前置处理点resolveBeforeInstantiation方法让我们可以实现自定义的bean创建步骤。一般情况下(典型),我们会使用它(前置处理)来阻止特定
bean执行默认的实例化流程。例如,使用代理的方式来创建特定bean(比如,延迟初始化的bean)。/** * Apply before-instantiation post-processors, resolving whether there is a * before-instantiation shortcut for the specified bean. */ @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // ...优化避免无效遍历 // 假设存在InstantiationAwareBeanPostProcessor扩展点 Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } return bean; } /** * Apply InstantiationAwareBeanPostProcessors to the specified bean definition * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods. * <p>Any returned object will be used as the bean instead of actually instantiating * the target bean. A {@code null} return value from the post-processor will * result in the target bean being instantiated. */ @Nullable protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { Object result = bp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } return null; } @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; }在
resolveBeforeInstantiation方法中,Spring会在一系列InstantiationAwareBeanPostProcessors上逐个执行其前置处理方法postProcessBeforeInstantiation,并将首个非空返回值传递到一系列BeanPostProcessor中逐个执行其后置处理方法postProcessAfterInitialization,然后忽略后续的属性填充和初始化流程直接返回当前的处理结果。需要注意,若
InstantiationAwareBeanPostProcessors#postProcessBeforeInstantiation返回非空实例即意味着bean的实例化已经完成,并不会继续执行原有的实例化流程了。也正因如此,在通过InstantiationAwareBeanPostProcessors#postProcessBeforeInstantiation获取到非空实例后会将其传递到一系列的BeanPostProcessor执行初始化后置处理postProcessAfterInitialization。
1. Bean的实例化
1.1. 实例创建
对于bean实例的创建,Spring是通过createBeanInstance方法来实现的。
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// ...
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// ...
// 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);
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* mbd parameter specifies a class, rather than a factoryBean, or an instance variable
* on a factory object itself configured using Dependency Injection.
*/
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
/**
* "autowire constructor" (with constructor arguments by type) behavior.
* Also applied if explicit constructor argument values are specified,
* matching all remaining arguments with beans from the bean factory.
* <p>This corresponds to constructor injection: In this mode, a Spring
* bean factory is able to host components that expect constructor-based
* dependency resolution.
*/
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
/**
* Instantiate the given bean using its default constructor.
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
// 假设非方法注入
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
在createBeanInstance方法中主要使用了3种(我们熟知的)方法来创建bean实例,分别是:
- 通过指定工厂方法构建
- 通过指定构造器构建构建
- 通过默认构造器构建
其中,最为简单的无疑就是通过默认构造器来构建bean实例了。在实现上,这种方式会从BeanDefinition中获取Class类型,然后通过反射机制来获取它的无参构造器并以此来创建出具体的实例对象。
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 假设非方法注入
Constructor<?> constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
// 假设无异常
final Class<?> clazz = bd.getBeanClass();
constructorToUse = clazz.getDeclaredConstructor();
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
// 通过反射生成实例对象
return BeanUtils.instantiateClass(constructorToUse);
}
}
而其他两种更为复杂的方式则会先使用当前BeanFactory实例构造出ConstructorResolver实例:
/**
* Delegate for resolving constructors and factory methods.
*
* <p>Performs constructor resolution through argument matching.
*/
class ConstructorResolver {
private final AbstractAutowireCapableBeanFactory beanFactory;
/**
* Create a new ConstructorResolver for the given factory and instantiation strategy.
* @param beanFactory the BeanFactory to work with
*/
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
然后,再通过其中基于工厂方法的ConstructorResolver#instantiateUsingFactoryMethod和基于构造器的ConstructorResolver#autowireConstructor方法来执行bean实例的创建,下面我们来看看它们是如何实现的:
基于构造器创建bean实例
与通过默认构造器构建bean实例类似,在基于指定构造器创建bean实例的ConstructorResolver#autowireConstructor方法中会在选出最终的构造器和构造参数后将它们传入instantiate方法中通过反射机制实现bean实例的创建。
/**
* Delegate for resolving constructors and factory methods.
*
* <p>Performs constructor resolution through argument matching.
*/
class ConstructorResolver {
private final AbstractAutowireCapableBeanFactory beanFactory;
/**
* "autowire constructor" (with constructor arguments by type) behavior.
* Also applied if explicit constructor argument values are specified,
* matching all remaining arguments with beans from the bean factory.
* <p>This corresponds to constructor injection: In this mode, a Spring
* bean factory is able to host components that expect constructor-based
* dependency resolution.
*/
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 最终选出的构造器
Constructor<?> constructorToUse = ...;
// 最终选出的构造参数
Object[] argsToUse = ...;
// ...
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
// 假设无异常
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
// 假设非方法注入
return BeanUtils.instantiateClass(ctor, args); // 通过反射生成实例对象
}
}
不难看出,与无指定构造器构建的相比这种方式上加多了对构造器和构造参数的解析和获取,那么下面我们来看看这里是如何进行解析的:
为了更加方便分析源码逻辑,下面代码中将部分非必要的或者易于理解的场景的代码隐藏掉,其中包括但不限于: 异常处理场景、缓存处理场景、仅存在一个无参构造器场景(直接通过反射机制生成实例对象)、显式传入参数场景等。
// 最终选出的构造器
Constructor<?> constructorToUse = null;
// 最终选出的构造参数
Object[] argsToUse = null;
// 获取构造器候选者(假设已经排序完成)
Constructor<?>[] candidates = ...;
// ... 处理“仅存在一个无参构造器场景” (会直接返回)
// Need to resolve the constructor.
boolean autowiring = ...;
// 创建构造器对象
ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
// 获取构造器参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 解析构造器参数
int minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
int minTypeDiffWeight = Integer.MAX_VALUE;
for (Constructor<?> candidate : candidates) {
// 假设parameterCount >= minNrOfArgs
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;
}
// ...
// 解析构造器参数类型
Class<?>[] paramTypes = candidate.getParameterTypes();
// 解析构造器参数名称
String[] paramNames = ...;
// 创建参数持有器,其中会解析自动装配的bean引用
ArgumentsHolder argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
// 通过argsHolder与paramTypes获取类型差异权重
int typeDiffWeight = ...;
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
}
// ...
}
在经过大量的精简后,构造器和构造参数的整个解析和获取流程显著凸显了出来,在这里我们将它分为5个步骤:
- 获取所有构造器候选者
- 获取
bean定义中声明的构造参数 - 解析
bean定义中声明的构造参数 - 构建构造参数数组(传入最终构造器进行实例化)
- 选出最终的构造器和构造参数(不断地循环第
4步和第5步对构造器进行比较)
其中,在这里我们重点关注一下包含了构造器注入的第3点和第4点,即解析bean定义中声明的构造参数和构建构造参数数组(含依赖自动注入的处理)。
-
解析
bean定义中声明的构造参数在第
3步中,Spring主要使用了resolveConstructorArguments方法对bean定义中显式指定的构造参数进行解析,在实现上它会分别对索引匹配的构造参数和类型匹配的构造参数逐个进行解析,并最终将解析结果存储到ConstructorArgumentValues中。其中,具体到参数值的解析是委托给了BeanDefinitionValueResolver#resolveValueIfNecessary方法来完成,它在解析时如果遇到其他bean引用则会使用BeanFactory#getBean进行获取。/** * Resolve the constructor arguments for this bean into the resolvedValues object. * This may involve looking up other beans. * <p>This method is also used for handling invocations of static factory methods. */ private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) { // ... BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); // 假设minNrOfArgs是正确的,无需更新 int minNrOfArgs = cargs.getArgumentCount(); // 处理索引匹配的参数 for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) { // 假设index符合条件 int index = entry.getKey(); ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); // 解析参数值,对于其他bean的引用会使用BeanFactory#getBean进行获取 Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); // ... resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder); } // 处理类型匹配的参数 for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) { // 解析参数值,对于其他bean的引用会使用BeanFactory#getBean进行获取 Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); // ... resolvedValues.addGenericArgumentValue(resolvedValueHolder); } return minNrOfArgs; }至此,
Spring完成了对bean定义中显式指定的构造参数的解析。 -
构建构造参数数组
在第
4步中,Spring主要使用了createArgumentArray方法对第3步解析的参数值进行组装,其中通过索引匹配的构造参数优先级比通过类型匹配的构造参数高,即优先取通过索引匹配的构造参数。在遇到匹配不到解析值的参数,Spring会使用自动装配的方式在IoC容器中进行寻找和匹配(若配置了自动装配),其中对于自动装配参数的匹配是交由resolveAutowiredArgument方法来完成,在解析时如果遇到其他bean引用它也会使用BeanFactory#getBean进行获取。/** * Create an array of arguments to invoke a constructor or factory method, * given the resolved constructor argument values. */ private ArgumentsHolder createArgumentArray( String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues, BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable, boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException { ArgumentsHolder args = new ArgumentsHolder(paramTypes.length); // ... for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { Class<?> paramType = paramTypes[paramIndex]; String paramName = (paramNames != null ? paramNames[paramIndex] : ""); // Try to find matching constructor argument value, either indexed or generic. ConstructorArgumentValues.ValueHolder valueHolder = null; if (resolvedValues != null) { ConstructorArgumentValues.ValueHolder valueHolder = null; if (resolvedValues != null) { // 分别从索引匹配的结果(优先)和类型匹配的结果中获取值。 valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, ...); // ... } } if (valueHolder != null) { // ... 将valueHolder赋值到args中 } else { // 假设autowiring为true,即标记了自动装配 MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // ... // 解析自动装配的参数值,在选出最终的引用后会使用BeanFactory#getBean进行获取(若需要) Object autowiredArgument = resolveAutowiredArgument( methodParam, beanName, autowiredBeanNames, converter, fallback); // ... 将autowiredArgument赋值到args中 } } // ... return args; } /** * Look for an argument value that either corresponds to the given index * in the constructor argument list or generically matches by type. */ @Nullable public ValueHolder getArgumentValue(int index, @Nullable Class<?> requiredType, @Nullable String requiredName, @Nullable Set<ValueHolder> usedValueHolders) { // 优先使用索引匹配结果来获取值 ValueHolder valueHolder = getIndexedArgumentValue(index, requiredType, requiredName); if (valueHolder == null) { // 其次才使用类型匹配结果获取值 valueHolder = getGenericArgumentValue(requiredType, requiredName, usedValueHolders); } return valueHolder; }至此,
Spring完成了对bean定义中自动装配的解析和对构造参数的组装。
基于工厂方法创建bean实例
在基于工厂方法创建bean实例的ConstructorResolver#instantiateUsingFactoryMethod方法中会在选出最终的工厂实例、工厂方法和方法参数后将它们传入instantiate方法中通过反射机制实现bean实例的创建。
class ConstructorResolver {
private final AbstractAutowireCapableBeanFactory beanFactory;
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* bean definition parameter specifies a class, rather than a "factory-bean", or
* an instance variable on a factory object itself configured using Dependency Injection.
* <p>Implementation requires iterating over the static or instance methods with the
* name specified in the RootBeanDefinition (the method may be overloaded) and trying
* to match with the parameters. We don't have the types attached to constructor args,
* so trial and error is the only way to go here. The explicitArgs array may contain
* argument values passed in programmatically via the corresponding getBean method.
*/
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 最终选出的工厂实例
Object factoryBean = ...;
// 最终选出的工厂方法
Method factoryMethodToUse = ...;
// 最终选出的工厂方法参数
Object[] argsToUse = ...;
// ...
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
// 假设无异常
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
return strategy.instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
// 假设无异常
ReflectionUtils.makeAccessible(factoryMethod);
// 忽略其他逻辑
Object result = factoryMethod.invoke(factoryBean, args); // 通过反射调用工厂方法
// 假设result不为null
return result;
}
}
也许在XML配置中,我们十分清晰通过工厂方法创建bean的概念,但在Java的配置方式中一般很难找到相关的概念。而实际上在Java的配置方式也是存在对应的概念的,也就是我们通过@Bean方法所声明的bean。其中,如果@Bean方法是实例方法则表示它是实例工厂方法,而如果@Bean方法是静态方法则表示它是静态工厂方法,那么自然而然的它们所在的@Configuration或者@Component配置类则是它们的工厂类factory-class或者工厂实例factory-bean。下面我们可以看到@Bean方法的解析代码:
/**
* Reads a given fully-populated set of ConfigurationClass instances, registering bean
* definitions with the given {@link BeanDefinitionRegistry} based on its contents.
*/
class ConfigurationClassBeanDefinitionReader {
/**
* Read the given {@link BeanMethod}, registering bean definitions
* with the BeanDefinitionRegistry based on its contents.
*/
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// ...
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
if (metadata.isStatic()) {
/**
* static @Bean method
*/
// 对于静态工厂方法仅需设置工厂类
if (configClass.getMetadata() instanceof StandardAnnotationMetadata sam) {
beanDef.setBeanClass(sam.getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
// 设置方法名字
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
/**
* instance @Bean method
*/
// 对于实例工厂方法需设置工厂实例
beanDef.setFactoryBeanName(configClass.getBeanName());
// 设置方法名字
beanDef.setUniqueFactoryMethodName(methodName);
}
// 设置方法对象
if (metadata instanceof StandardMethodMetadata sam) {
beanDef.setResolvedFactoryMethod(sam.getIntrospectedMethod());
}
// 设置为自动装配
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
// ...
}
}
在loadBeanDefinitionsForBeanMethod方法中我们可以发现在解析@Bean时它会根据是否属于static分别对静态工厂方法和实例工厂方法进行赋值,即对于静态工厂方法设置factory-class(bean-class)和对应的静态方法;而对于实例工厂方法则设置factory-bean和对应的实例方法。另外,在loadBeanDefinitionsForBeanMethod方法中并没有对@Bean的方法参数进行解析,而是将autowire-mode属性设置为AUTOWIRE_CONSTRUCTOR,即在构造实例时通过自动装配的方式完成参数的赋值(可简单理解为使用构造参数自动装配的方式完成赋值)。
在了解这个概念后,下面我们再来看看Spring是如何对它进行解析的:
为了更加方便分析源码逻辑,下面代码中将部分非必要的或者易于理解的场景的代码隐藏掉,其中包括但不限于: 异常处理场景、缓存处理场景、仅存在一个无参工厂方法场景(直接通过反射机制生成实例对象)、显式传入参数场景等。
// 最终选出的工厂实例
Object factoryBean = null; // 静态工厂方法的factoryBean为null
// 最终选出的工厂方法
Method factoryMethodToUse = null;
// 最终选出的工厂方法参数
Object[] argsToUse = null;
// factoryBeanName属性指的是工厂实例bean的名称,而不是FactoryBean实例的名称
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
//...
factoryBean = this.beanFactory.getBean(factoryBeanName);
}
// ...
// 获取工厂方法候选者
List<Method> candidates = ...;
// ... 处理“仅存在一个无参工厂方法场景” (会直接返回)
boolean autowiring = ...;
// 获取工厂方法参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 获取工厂方法参数
ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
// 解析工厂方法参数
int minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
int minTypeDiffWeight = Integer.MAX_VALUE;
for (Method candidate : candidates) {
// 假设parameterCount >= minNrOfArgs
int parameterCount = candidate.getParameterCount();
// 解析工厂方法参数类型
Class<?>[] paramTypes = candidate.getParameterTypes();
// 解析工厂方法参数名称
String[] paramNames = ...;
// 创建参数持有器,其中会解析自动装配的bean引用
ArgumentsHolder argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
// 通过argsHolder与paramTypes获取类型差异权重
int typeDiffWeight = ...;
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
}
// ...
}
// ...
在经过大量的精简后,工厂方法和方法参数的整个解析和获取流程显著凸显了出来,在这里我们将它分为5个步骤:
- 获取所有工厂方法候选者
- 获取
bean定义中声明的工厂方法参数 - 解析
bean定义中声明的工厂方法参数 - 构建工厂方法参数数组(传入最终工厂方法进行实例化)
- 选出最终的工厂方法和工厂方法参数(不断地循环第
4步和第5步对构造器进行比较)
如果阅读过上文关于“基于构造器创建bean实例“模块的源码分析,不难发现对于第3步和第4步的逻辑几乎是相同的,所以在这里笔者就不再展开分析了。其中,根据上文对@Bean工厂方法的解析我们可以得知对于@Bean方法参数的解析是在createArgumentArray方法中通过自动装配的方式完成的,而非通过resolveConstructorArguments方法完成解析的,这是因为在@Bean方法解析时并没有解析方法参数到ConstructorArgumentValues中,而是将方法解析对象的autowire-mode属性设置为AUTOWIRE_CONSTRUCTOR,即使用自动装配完成参数值的设置。
也许有细心的读者在分析“基于工厂方法构建bean实例”的过程中会发现它也采用了与“基于构造器构建bean实例”相同的方法与概念,即带有构造器字眼的参数和方法:ConstructorArgumentValues参数、ConstructorArgumentValues参数和resolveConstructorArguments方法等,这实际上是因为在工厂方法的执行过程中将方法参数充当了类似于构造器参数那样必须的存在,所以在逻辑相同的情况下复用了具有相同效果的参数与方法。与此同时,这样的设计方案也导致了在Spring处理循环依赖时无法有效的解决工厂方法参数上的循环依赖。
需要注意的是,
Spring在处理实例工厂方法时会首先通过BeanFactory#getBean向IoC容器请求(获取/创建)它的工厂实例(factory-bean),而静态工厂方法则不会触发这一步骤。
1.2. 属性前置处理
在完成bean实例的创建后,我们就可以进行属性的填充了。但是在属性填充前,Spring还提供了applyMergedBeanDefinitionPostProcessors方法让我们可以进行bean的属性前置处理,即将BeanDefinition传入每个MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition方法进行前置处理。
/**
* Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
* invoking their {@code postProcessMergedBeanDefinition} methods.
* @param mbd the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
1.3. 属性加载
在完成bean属性的前置处理后,我们就顺着执行流程进入到populateBean方法进行属性的填充了。
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...
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;
}
// ... 属性后置处理
// ... 检查依赖
// ... 属性填充
}
在populateBean方法中Spring会根据自动装配的类型AUTOWIRE_BY_NAME(按照beanName进行匹配)和AUTOWIRE_BY_TYPE(按照beanType进行匹配)分别调用autowireByName方法和autowireByType完成装配。其中,为了可以更清晰地分析bean属性的加载过程,下面我们将基于autowireByName方法来进一步分析。
/**
* Fill in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
* @param beanName the name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
* @param mbd bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 通过BeanFactory#getBean加载propertyName对应的bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
在autowireByName方法中我们可以看到Spring会对未加载的beanName传入BeanFactory#getBean中进行加载,并最终将它加入到MutablePropertyValues中。
1.4. 属性后置处理
在完成bean属性的加载后,Spring提供了一个基于InstantiationAwareBeanPostProcessor的扩展点postProcessProperties使得我们可以对加载后的属性进行后置处理,即将PropertyValues传入每个InstantiationAwareBeanPostProcessor中的postProcessProperties方法进行后置处理。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// ... 属性加载
// 假设存在InstantiationAwareBeanPostProcessor扩展点
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
pvs = pvsToUse;
}
// ... 检查依赖
// ... 属性填充
}
1.5. 属性填充
在完成一系列的bean属性处理后,Spring就通过applyPropertyValues执行属性的填充了,具体如下所示:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// ... 属性加载
// ... 属性后置处理
// ... 检查依赖
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName the bean name passed for better exception information
* @param mbd the merged bean definition
* @param bw the BeanWrapper wrapping the target object
* @param pvs the new property values
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// ...
MutablePropertyValues mpvs = ...;
List<PropertyValue> original = ...;
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, ...);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
// ... Add pv to deepCopy after converting it
deepCopy.add(pv after converting)
}
// ...
// Set our (possibly massaged) deep copy.
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
在applyPropertyValues方法中,Spring会将所有的PropertyValue属性经过转换后添加到BeanWrapper的propertyValues属性后结束执行。
除此之外,如果我们想忽略
populateBean方法中属性填充的执行,那么我们可以使用Spring提供的一个扩展点InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation让我们可以提前终止bean属性的填充,具体如下所示:protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // ... // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. // 假设存在InstantiationAwareBeanPostProcessor扩展点 for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } // ... 属性加载 // ... 属性后置处理 // ... 检查依赖 // ... 属性填充 }
至此,bean的实例化阶段完成。
2. Bean的初始化
在完成bean的实例化后,Spring就开始执行initializeBean方法完成bean实例的初始化了。
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 执行aware方法
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
// 假设可执行前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 假设没有异常
invokeInitMethods(beanName, wrappedBean, mbd);
// 假设可执行后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
在
bean实例的初始化前,首先会使用Aware接口注入部分bean属性(具体可阅读invokeAwareMethods方法),然后才真正开始bean实例的初始化流程。
根据上述初始化代码的分析,我们很轻易的就可以将bean的初始化流程分为3个步骤,即:
- 初始化前置处理
- 初始化实例
- 初始化后置处理
为了更清晰地阐述bean的初始化流程,下面笔者将分点逐个进行分析。
对于初始化的前置处理和后置处理
Spring主要是通过BeanPostProcessor来完成。对于BeanPostProcessor,它所提供的能力在Spring中常常发挥着重要的作用,例如常用的Spring注解和Spring AOP都是通过它来实现的。
2.1. 初始化前置处理
Bean的初始化前置处理主要通过applyBeanPostProcessorsBeforeInitialization方法完成。
@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;
}
在实现上,applyBeanPostProcessorsBeforeInitialization方法中会将bean传入每个BeanPostProcessor中的postProcessBeforeInitialization方法进行前置处理,直到遍历所有的BeanPostProcessor或者在遇到第一个返回null时结束并返回结果。
2.2. 初始化实例
Bean的初始化处理主要是通过invokeInitMethods方法完成,下面我们可以看到invokeInitMethods方法的源码:
/**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
*/
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null && bean.getClass() != NullBean.class) {
String[] initMethodNames = mbd.getInitMethodNames();
if (initMethodNames != null) {
for (String initMethodName : initMethodNames) {
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd, initMethodName);
}
}
}
}
}
/**
* Invoke the specified custom init method on the given bean.
* Called by invokeInitMethods.
* <p>Can be overridden in subclasses for custom resolution of init
* methods with arguments.
*/
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd, String initMethodName)
throws Throwable {
// 假设存在initMethod
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());
// 假设无异常
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
根据对源码的分析,invokeInitMethods方法主要可分为两大步骤:
- 首先会判断当前
bean是否InitializingBean,若当前bean属于InitializingBean并且其中的afterPropertiesSet方法不属于外部管理(可简单理解为未使用@PostConstruct标注),则直接执行它的InitializingBean#afterPropertiesSet方法。 - 然后,再从
RootBeanDefinition中获取自定义的initMethod(通过配置属性指定的,具体可翻看上文),判断它是否属于InitializingBean的afterPropertiesSet方法或者被外部管理的initMethod,若都不属于则通过反射逐个调用。
关于
RootBeanDefinition中的externallyManagedInitMethods属性用于记录被外部管理的的initMethod,例如通过JSR-250的@PostConstruct注解所声明的initMethod就属于被外部管理的的initMethod。我们可以看到上述invokeInitMethods方法中出现的hasAnyExternallyManagedInitMethod方法是如何判断的:private Set<String> externallyManagedInitMethods; /** * Register an externally managed configuration initialization method — * for example, a method annotated with JSR-250's * {@link jakarta.annotation.PostConstruct} annotation. * <p>The supplied {@code initMethod} may be the * {@linkplain Method#getName() simple method name} for non-private methods or the * {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method) * qualified method name} for {@code private} methods. A qualified name is * necessary for {@code private} methods in order to disambiguate between * multiple private methods with the same name within a class hierarchy. */ public void registerExternallyManagedInitMethod(String initMethod) { if (this.externallyManagedInitMethods == null) { this.externallyManagedInitMethods = new LinkedHashSet<>(1); } this.externallyManagedInitMethods.add(initMethod); } /** * Determine if the given method name indicates an externally managed * initialization method, regardless of method visibility. * <p>In contrast to {@link #isExternallyManagedInitMethod(String)}, this * method also returns {@code true} if there is a {@code private} externally * managed initialization method that has been * {@linkplain #registerExternallyManagedInitMethod(String) registered} * using a qualified method name instead of a simple method name. */ boolean hasAnyExternallyManagedInitMethod(String initMethod) { if (isExternallyManagedInitMethod(initMethod)) { return true; } if (this.externallyManagedInitMethods != null) { for (String candidate : this.externallyManagedInitMethods) { // 对于全限定名称则直接截取最后的方法名进行判断 int indexOfDot = candidate.lastIndexOf('.'); if (indexOfDot >= 0) { String methodName = candidate.substring(indexOfDot + 1); if (methodName.equals(initMethod)) { return true; } } } } return false; } /** * Determine if the given method name indicates an externally managed * initialization method. * <p>See {@link #registerExternallyManagedInitMethod} for details * regarding the format for the supplied {@code initMethod}. */ public boolean isExternallyManagedInitMethod(String initMethod) { return (this.externallyManagedInitMethods != null && this.externallyManagedInitMethods.contains(initMethod)); }在上述方法中主要是对
RootBeanDefinition中的externallyManagedInitMethods属性进行新增和匹配。其中,Spring会使用registerExternallyManagedInitMethod方法对它进行新增,使用hasAnyExternallyManagedInitMethod方法或者isExternallyManagedInitMethod方法将传入的initMethod参数与externallyManagedInitMethods属性进行比较并最终返回判断结果。
2.3. 初始化后置处理
Bean的初始化后置处理主要通过applyBeanPostProcessorsAfterInitialization方法完成。
@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;
}
在实现上,applyBeanPostProcessorsAfterInitialization方法中会将bean传入每个BeanPostProcessor中的postProcessAfterInitialization方法进行前置处理,直到遍历所有的BeanPostProcessor或者在遇到第一个返回null时结束并返回结果。
至此,bean的初始化阶段完成。
关于
getObjectForBeanInstance方法的调用在上文
doGetBean方法的执行流程中,不难发现无论是从缓存中获取bean还是主动创建bean,它都会将获取到的bean实例传递到getObjectForBeanInstance方法中进一步处理,这其实是针对FactoryBean所提供的特殊处理。在这里我们借着这个机会对FactoryBean的实现原理一探究竟:在进入源码分析前,首先我们先来回顾一下上文对
FactoryBean的描述:对于使用
FactoryBean所声明的bean,Spring会将FactoryBean及其FactoryBean#getObject方法返回的对象都注册到IoC容器中。其中,对于FactoryBean指定或默认生成的名称是其FactoryBean#getObject所创建的bean实例名称,而FactoryBean实例本身的名称则需在指定或默认生成的名称前加上前缀&,即&beanName。也就是说,对于使用
FactoryBean所声明的bean会产生如下结果:
- 类型为
FactoryBean、名字为&beanName的bean实例。- 类型为
FactoryBean#getObject、名字为beanName的bean实例。下面,我们将带着这两个结果的预期对
getObjectForBeanInstance方法进行阅读与分析:public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { /** * Get the object for the given bean instance, either the bean * instance itself or its created object in case of a FactoryBean. * @param beanInstance the shared bean instance * @param name the name that may include factory dereference prefix * @param beanName the canonical bean name * @param mbd the merged bean definition * @return the object to expose for the bean */ protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // 假设mbd不为空 // 判断name是否带有&前缀 if (BeanFactoryUtils.isFactoryDereference(name)) { // ... return beanInstance; } // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean<?> factoryBean)) { return beanInstance; } // ... Object object = getObjectFromFactoryBean(factoryBean, beanName, ...); return object; } }根据对代码的理解,对于
getObjectForBeanInstance方法的入参主要有3个需要注意的:
参数 说明 namename参数表示请求时所指定bean的原始名称。其中,对于FactoryBean则格式为&beanName;对于FactoryBean#getObject则格式为beanName。beanNamebeanName参数表示请求时所指定的name参数在经过处理后的名称。其中,对于FactoryBean则格式为beanName;对于FactoryBean#getObject则格式为beanName。beanInstancebeanInstance参数表示通过beanName参数请求获得的bean实例。如果是FactoryBean的定义,则表示FactoryBean实例本身。不难得出,对于
name参数值为&beanName格式的请求,Spring仅仅会将它用作是标识客户端向IoC容器请求FactoryBean实例本身而不是FactoryBean#getObject返回的实例。在简化掉一些赋值语句与非核心判断逻辑后,
getObjectForBeanInstance方法的整体流程就十分清晰了:
- 首先判断
name参数是否带有&前缀,如果是则返回beanInstance实例,否则继续往下执行。在这一步中Spring已经知道客户端是否需要获取FactoryBean实例本身(Spring定义了带有&前缀的beanName为FactoryBean实例)。- 然后判断当前
beanInstance是否属于FactoryBean实例,如果不是则返回beanInstance实例,否则继续往下执行。在这一步中Spring已经完成普通bean实例的处理(非FactoryBean实例)。- 最后将
beanInstance传入getObjectFromFactoryBean方法获取FactoryBean#getObject所返回的对象。在经过第1步和第2步的前置处理后,这一步中所处理的对象目标必然是FactoryBean#getObject所返回的对象。接下来,我们再来看看
getObjectFromFactoryBean方法是如何处理FactoryBean#getObject所返回的对象的。/** * Support base class for singleton registries which need to handle * {@link org.springframework.beans.factory.FactoryBean} instances, * integrated with {@link DefaultSingletonBeanRegistry}'s singleton management. * * <p>Serves as base class for {@link AbstractBeanFactory}. */ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry { /** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @param shouldPostProcess whether the bean is subject to post-processing * @return the object obtained from the FactoryBean */ protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, ...) { if (factory.isSingleton() && containsSingleton(beanName)) { // ...此处加了synchronized锁保证了这段代码的线程安全 Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); // Only post-process and store if not put there already during getObject() call above // (e.g. because of circular reference processing triggered by custom getBean calls) Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // ... // 假设条件符合,执行初始化后置处理 object = postProcessObjectFromFactoryBean(object, beanName); if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } return object; } } else { Object object = doGetObjectFromFactoryBean(factory, beanName); // 假设条件符合,执行初始化后置处理 object = postProcessObjectFromFactoryBean(object, beanName); } return object; } /** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @return the object obtained from the FactoryBean */ private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException { Object object = factory.getObject(); return object; } } public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { /** * Applies the {@code postProcessAfterInitialization} callback of all * registered BeanPostProcessors, giving them a chance to post-process the * object obtained from FactoryBeans (for example, to auto-proxy them). * @see #applyBeanPostProcessorsAfterInitialization */ @Override protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { return applyBeanPostProcessorsAfterInitialization(object, beanName); } @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; } }在
getObjectFromFactoryBean方法中就有对FactoryBean#getObject单例作用域与非单例作用域的处理了。具体地,这里分为两种情况:
单例作用域,即
FactoryBean实例属于单例作用域,且FactoryBean#isSingleton为true的情况(与上文FactoryBean单例作用域说明呼应)。
- 首先从
factoryBeanObjectCache缓存中获取beanName对应的实例(factoryBeanObjectCache缓存专门用于存储FactoryBean#getObject创建的对象),如果获取失败则继续往下执行。- 然后执行
doGetObjectFromFactoryBean方法使用FactoryBean#getObject创建bean对象。- 接着再次从
factoryBeanObjectCache缓存中获取beanName对应的实例(用于处理循环依赖问题)。
- 如果能从
factoryBeanObjectCache缓存中获取到,则使用缓存中的对象而不是使用FactoryBean#getObject创建的。- 如果不能从
factoryBeanObjectCache缓存中获取到,则确定使用FactoryBean#getObject创建的对象,并对它执行以下步骤。
- 将实例传入初始化后置处理
BeanPostProcessor#postProcessAfterInitialization方法执行。- 将结果放入到
factoryBeanObjectCache缓存中(保证了FactoryBean#getObject创建对象的单例作用域特性)。- 将获取/创建的
bean对象返回。在上述第
3步中重复再次从factoryBeanObjectCache缓存中获取beanName对应的实例主要是为了处理循环依赖所产生的问题,从而避免在单例作用域下返回各不相同的实例。需要注意,对于第3步中重复地从factoryBeanObjectCache缓存中获取实例会很容易让人误以为是针对多线程并发的处理,实际上因为if代码块开头加入了synchronized的锁机制,所以此处并不会发生并发的场景。下面,我们将结合例子对此作进一步阐述:@Component public class CircularBeanFactoryBean implements FactoryBean { @Autowired private ApplicationContext applicationContext; @Override public boolean isSingleton() { return true } @Override public Class getObjectType() { return CircularBean.class; } @Override public Object getObject() { CircularDependency dependency = applicationContext.getBean(CircularDependency.class); return new CircularBean(dependency); } } public class CircularBean { private CircularDependency circularDependency; public CircularReferenceBean(CircularDependency circularDependency) { this.circularDependency = circularDependency; } } @Component public class CircularDependency { @Autowired private CircularBean circularBean; }在例子中,当
Spring首次创建CircularBeanFactoryBean实例后会通过getObjectFromFactoryBean方法获取其中CircularBean实例。按照下述执行步骤:
- 首先从
factoryBeanObjectCache获取CircularBean实例,显然当前并不存在CircularBean实例。- 然后执行
doGetObjectFromFactoryBean方法时使用FactoryBean#getObject创建CircularBean实例。
- 通过
ApplicationContext#getBean获取CircularDependency实例,而在获取/创建CircularDependency实例的过程中会再次加载它的依赖CircularBean(发生循环依赖),此时会再次触发getObjectFromFactoryBean方法:
- 首先从
factoryBeanObjectCache获取CircularBean实例,因为在外层的尚未创建完CircularBean实例,所以此时还是会获取失败。- 然后执行
doGetObjectFromFactoryBean方法使用FactoryBean#getObject创建CircularBean对象。其中,FactoryBean#getObject再次执行时触发的CircularDependency实例获取(通过ApplicationContext#getBean)由于Spring对bean循环依赖的解决方案使得此次直接可以从缓存中获取(而不是再次触发创建),最终将CircularDependency实例传入CircularBean构造函数完成CircularBean实例的创建(第1个CircularBean实例被创建了)。- 接着将
CircularBean实例放入到factoryBeanObjectCache缓存中。- 最后将
CircularBean实例返回并结束外层CircularDependency依赖的创建。- 将
CircularDependency依赖传入CircularBean构造函数中完成CircularBean实例的创建(第2个CircularBean实例被创建了,即此时存在2个CircularBean实例)。- 最后再次从
factoryBeanObjectCache缓存中获取CircularBean实例,此时由于在第2.1步中已经将创建的CircularBean实例存放到factoryBeanObjectCache缓存中,所以此时能从缓存中获取到CircularBean实例并使用它覆盖第2.2步中创建的CircularBean实例(如果不进行覆盖则会创建出2个CircularBean实例,这并不符合单例作用域的特性)。最终,
Spring通过这种缓存的方式解决了单例作用域下FactoryBean循环依赖所产生的多实例产生问题。非单例作用域(多例作用域)
相比于单例作用域,非单例作用域(多例作用域)的处理逻辑则简单很多,即每次都使用
doGetObjectFromFactoryBean方法创建bean实例,然后将实例传入初始化后置处理BeanPostProcessor#postProcessAfterInitialization方法执行,最后将执行结果返回。总的来说,
FactoryBean实例和FactoryBean#getObject实例实际上所使用的beanName都是相同的,只是它们存储的容器有所不同(特指单例作用域)。而Spring在处理bean请求时会根据命名中是否带有&前缀来区分客户端是想获得/创建FactoryBean实例本身还是FactoryBean#getObject实例。另外需要注意的是,要将FactoryBean#getObject返回的实例指定为单例作用域,不但需要让FactoryBean#isSingleton设置为true,而且还需要将FactoryBean实例本身设置为单例作用域。