准备创建bean
我们不可能在一个函数完成完整的逻辑,而且String源码有一个规律:一个真正干活的函数都是以do开头的。其他函数一般是做统筹的。createBean函数也不例外:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("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 {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 给BeanPostProcessors一个机会来返回代理来替换真正的实例
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);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
从代码中我们可以总结出函数完整的实现步骤及功能。
- 根据设置的class属性或者根据className来解析Class
- 对Override属性进行标记和验证
很多读者可能并不知道这个方法的作用,因为在Spring的配置里面根本就没有诸如override-method之类的配置,那么这个方法到底是干什么用的呢?
其实在Spring中确实没有Override-method这样的配置,但是如果读过前面的部分,可能会有所发现,在Spring配置中是存在lookup-method和replace-method的,而这两个配置的加载其实就是将配置统一放在BeanDefinition中的methodOverrides属性中,而这个函数的操作其实也是针对这两个配置的。
- 3.应用初始化前的后处理器,解析指定Bean是否存在初始化前的短路操作。
- 4.创建bean
处理Override属性
查看源码中AbstractBeanDefinition类的prepareMethodOverrides方法,其实这里面的处理就是将lookup-method和replace-method属性放入BeanDefinition中的methodOverrides属性中。这两个功能实现原理其实就是在bean实例化的时候如果检测到存在methodOverrides属性,会动态地为当前bean生成代理并使用对应的拦截器为bean做增强处理,相关逻辑实现在bean的实例化部分详细介绍。
但是这里要提到的是,对于方法的配置来讲,如果一个类中存在若干个重载方法,那么,在函数调用及增强的时候还需要根据参数类型进行配置,来最终确认当前调用的是哪个函数。但是,Spring将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么就设置重载方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对该方法的存在性进行验证,正可谓一箭双雕。
实例化的前置处理
在真正调用doCreate方法之前使用了resolveBeforeInstantiation对BeanDefinition中的属性做些前置处理。当然无论其中是否有相应的逻辑实现我们都可以理解,因为真正逻辑实现前后留有处理函数也是可扩展的一种体现,但是,这并不是最重要的,在函数中还提供了一个短路判断,这才是最关键的部分。
当经过前置处理后返回的结果如果不为空,那么会直接略过后续的bean的创建而直接返回结果。这一特性虽然很容易被忽略,但是却起着至关重要的作用,我们熟知的AOP功能就是基于这里的判断的。
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方法的调用。
实例化前的后处理器应用
bean的实例化前调用,也就是将AbstractBeanDefinition转换为BeanWrapper前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们认为的bean了,而是或许成为了一个经过处理的代理Bean,可能是通过cglib生成的,也可能是通过其他技术生成的。以后介绍,我们只需要知道,在bean的实例化前会调用后处理器的方法进行处理。
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
实例化后的后处理器应用
在讲解从缓存中获取单例bean的时候就提到过,Spring中的规则是在bean的初始化后尽可能保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法。
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}