我们不可能指望在一个函数中完成一个复杂的逻辑,而且我们或多或少发现一些规律:一个真正干活的函数其实是以 do 开头的,比如 ​​FactoryBeanRegistrySupport#doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)​​​;而给我们错觉的函数,比如 ​​FactoryBeanRegistrySupport#getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)​​​ 其实只是从全局角度去做一些统筹的工作。这个规则对 九、Spring 源码解析之 bean 的加载流程四: 从缓存中获取不到单例 bean时,获取单例处理 文章最后提到的 ​​createBean()​​​ 方法也不例外。 ​​createBean()​​​ 方法是一个抽象方法,真正实现是 ​​AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)​​​,让我们看看 ​​createBean()​​ 方法做了哪些准备工作。

@Override
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;

//锁定 class,根据设置的 class 属性或者根据 className 来解析 class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// Prepare method overrides.
try {
/*
* 对 override 属性进行标记及验证
* 在 Spring 中确实没有 `override-method` 这样的配置,但是在 Spring 配置中是存在 `lookup-method` 和
* `replace-method` 的,而这两个配置的加载其实就是将配置统一存放在 `BeanDefinition` 中的 `methodOverrides`
* 属性里,而这个函数的操作其实也就是针对于这两个配置的。
*/
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给 BeanPostProcessors 一个机会来返回代理来替代真正的实例
//应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
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);
}
}

该方法的具体步骤及功能:

  1. 根据设置的 class 属性或者根据 className 来解析 Class
  2. 对 override 属性进行标记及验证
    在 Spring 中确实没有​​​override-method​​​ 这样的配置,但是在 Spring 配置中是存在​​lookup-method​​​ 和​​replace-method​​​ 的,而这两个配置的加载其实就是将配置统一存放在​​BeanDefinition​​​ 中的​​methodOverrides​​ 属性里,而这个函数的操作其实也就是针对于这两个配置的。
  3. 应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
  4. 创建 bean。
    我们首先来看下对 override 属性标记及验证的逻辑实现。

一、处理 override 属性

  查看源码中 ​​AbstractBeanDefinition#prepareMethodOverrides()​​ 方法:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
if (hasMethodOverrides()) {
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
}

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
//获取对应类中对应方法名的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
//标记 MethodOverride 暂未被覆盖,避免参数类型检查的开销
mo.setOverloaded(false);
}
}

  之前提到过,在 Spring 配置中存在 ​​lookup-method​​​ 和 ​​replace-method​​​ 两个配置功能,而这两个配置的加载其实就是将配置统一存放在 ​​BeanDefinition​​​ 中的 ​​methodOverrides​​​ 属性里,这两个功能实现原理其实是在 bean 实例化的时候如果检测到存在 ​​methodOverrides​​​ 属性,会动态为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理,相关逻辑实现在 bean 的实例化部分详细介绍。
  但是,这里提到的是,对于方法的匹配来讲,如果一个类中存在若干个重载的方法,name,在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。但是,Spring 将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么久设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证

二、实例化的前置处理

  在真正调用 ​​doCreate()​​​ 方法创建 bean 的实例前使用了这样一个方法 ​​resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)​​​ 对 ​​BeanDefinition​​ 中的属性做些前置处理。当然,无论其中是否有相应的逻辑实现我们都可以理解,因为真正逻辑实现前后留有处理函数也是可扩展的一种体现,但是这不是最重要的,在函数中还提供了一个短路判断,这才是最为关键的部分。

if (bean != null) {
return bean;
}

  当经过前置处理后返回的结果如果不为空,那么会直接略过后续的 bean 的创建而直接返回结果。这一特性虽然很容易被忽略,但是却起着至关重要的作用,我们熟知的 AOP 功能就是基于这里的判断的。

@Nullable
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 = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

  此方法中最吸引我们的无疑是两个方法 ​​applyBeanPostProcessorsBeforeInstantiation()​​​ 和 ​​applyBeanPostProcessorsAfterInitialization()​​​ 。这两个方法实现的非常简单,无非是对后处理器中的所有 ​​InstantiationAwareBeanPostProcessor​​​ 类型的后处理器进行 ​​postProcessBeforeInstantiation()​​​ 处理和所有 ​​BeanPostProcessor​​​ 类型的后处理器进行 ​​postProcessAfterInitialization()​​ 处理。

1.实例化前的后处理器应用

@Nullable
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;
}

  bean 的实例化前调用,也就是将 AbstractBeanDefinition 转换为 BeanWrapper 前的处理。给子类一个修改 BeanDefinition 的机会,也就是说当程序经过这个方法后,bean 可能已经不是我们认为的 bean 了,而是或许成为一个经过处理的代理 bean,也可能是通过 cglib 生成的,也可能是通过其他技术生成的。在这里我们只需要知道,在 bean 的实例化前后调用后处理器的方法进行处理。

2.实例化后的后处理器应用

  在讲解从缓存中获取单例 bean 的时候就提到过,Spring 中的规则是在 bean 的初始化后尽可能保证将注册的后处理器的 ​​postProcessAfterInitialization()​​​ 方法应用到该 bean 中,因为如果返回得到 bean 不为空,那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 ​​postProcessAfterInitialization()​​ 方法。

@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;
}