❝结束了上半年的单身,开始下半年的单身.但是文章还是要写的,期待与你的共同进步.
❞
1.前情提要
上篇文章介绍到了 singletonFactory.getObject() 是一个复杂的过程,在这个过程中会触发 Bean的实例化。
今天这篇文章接续上一篇文章,在开始文章之前,我首先要做的是通过断点调试的方式来看看,方法的调用过程。
从上图中可以看出,在调用到 singletonFactory.getObject() 的时候会调用到doGetBean()方法中的lambda表达式中的 createBean ()方法,今天文章的开始就是这个方法。
2.正式进入createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
/** 判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器载入 */
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
/**
* 处理lookup-method 和 replace-method配置,spring将这两个方法统称为 method overrides
*/
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果Bean配置了PostProcessor,这里返回的是一个Proxy
// 这里配置的后置处理器,返回的对象 不会维护对象之间的关系
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 在配置了PostProcessor的处理器中 改变了Bean,直接返回
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
/**
* 创建Bean的实例
*/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
这里的 createBean() 是以回调函数的形式在方法中执行的,我们发现,该方法主要完成的具体步骤即功能:
①:根据设置的 class 属性或者根据 className 来解析 Class;
②:对 override 属性进行标记处理及验证;
❝
这里对于 lookup-method 和 replace-method 的处理,我们暂时放一放。本着抓主要矛盾方式我们先继续向下看,这部分的知识点之后再学习。
❞③:实例化前的后置处理器,解析指定
bean是否存在生成实例前的短路操作;❝
在实例化之前, 给 BeanPostProcessors 一个处理的机会,返回一个被代理的对象。这里如果返回的对象不为null,则直接返回。由此可知,这里返回的 对象是不会维护对象之间的关系的。
❞④:创建bean
❝
doCreateBean 方法,当看到doXXX 的方法,在Spring 中不用多说就是比较重要的方法了,这个是真正创建
❞Bean的地方。
3.插手Bean的实例化
提到插手二字,我们可能会不由的想到Spring中的后再处理器,和Bean相关的那就是BeanPostProcessor跑不了。这里看到的 resolveBeforeInstantiation()方法就是涉及 BeanPostProcessor的处理。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
/** 如果尚未被解析*/
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 确定目标类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// bean的前置处理器
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// bean的后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
上述方法中设计到两个子过程 applyBeanPostProcessorsBeforeInstantiation () 和 applyBeanPostProcessorsAfterInitialization()。
3.1 前置处理
首先上来先二话不说,字面理解一下「前置处理」,当然就是指在创建之前的处理。applyBeanPostProcessorsBeforeInstantiation()方法:
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
可以看出,这里是一个循环处理的过程,先获取到所有的 BeanPostProcessor 的实现,然后判断为 InstantiationAwareBeanPostProcessor
的子类的话,就挨个调用 postProcessBeforeInstantiation。可以通过下图简单的看一下,具体的代码实现,这里就先不赘述了。

3.2后置处理
在创建完成之后的处理。可能是关于一些属性的处理applyBeanPostProcessorsAfterInitialization()方法:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
// existingBean 为原对象
Object result = existingBean;
// 获取所有的 BeanPostProcessor 循环处理
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这个方法的执行,是在执行完 applyBeanPostProcessorsBeforeInstantiation 后所得对象不为 null 的情况下执行的。同样这里的
方法也不做赘述。
这里关于 BeanPostProcessor 的判断是,实现了 InstantiationAwareBeanPostProcessor 的类才会执行。通过实现 InstantiationAwareBeanPostProcessor
来干预 Bean 的生命周期。 之前文章中提到的关于 BeanPostProcessor的子类的处理,是在初始化的时候插手初始化过程。这里实现了 InstantiationAwareBeanPostProcessor 是
插手 Bean 的实例化过程,这里的实例化就是指对象的创建。关于 BeanPostProcessor 来说,在Spring中的设计是用来扩展对 bean 的处理。从这里可以看出,在Spring内部做了更加细节的处理,
区分了「初始化」与「实例化」。
3.3插手Bean实例化的BeanPostProcessor实现
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
从接口的定义中可以看出,接口中定义的都是 default 方法,都有自己的默认实现。postProcessBeforeInstantiation 这个是在对象创建之前
执行的方法,该方法默认返回 null。如果子类重写的话,可以按照自己需要的逻辑返回对象。若经过这一步返回的对象不为null,说明对象已经被创建了。
postProcessAfterInstantiation 是在对象创建完成之后做的,对上一步骤生成的对象做相应的处理。同样postProcessPropertyValues也对已经生成的
对象的属性进行修改。
4.创建Bean过程中的插手
从Spring中的代码实现来看,如果这里有相应的Bean被创建,那么就会直接返回实例化的Bean。也就是说这里创建的Bean尚未完成依赖关系的注入,即该对象中如果注入了其他类,那么改注入的类必为null.

本文使用 mdnice 排版