一、介绍
xxx()方法是来做一些准备、辅助之类的工作,真正干活儿的大部分会有一个与之对应的doXxx()方法。createBean()方法也不例外,真正的创建逻辑在doCreateBean()方法中。在真正创建bean之前,会做一些验证、处理的工作。本章就详细介绍一下,创建bean之前具体都执行了哪些步骤。
二、bean加载流程
- 获取用户传入name对应的beanName
- 尝试从缓存中获取bean实例
- 缓存中不存在,加载bean实例 3.1. 检查循环依赖 3.2 处理parentBeanFactory 3.3 处理依赖的bean(dependsOn) 3.4 三种bean实例的创建 3.4.1 单例bean的创建 3.4.1.1 获取单例bean,getSingleton()方法 3.4.1.2 准备创建bean,createBean()方法(本章解析) 3.4.1.3 创建bean,doCreateBean()方法 3.4.2 原型bean的创建 3.4.3 根据scope策略创建bean
- 从bean实例中获取真正的对象
- 转换对象类型
- 返回对象实例
三、相关类及方法
- org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean:加载一个Bean的整体过程都在这个方法中
- org.springframework.beans.factory.support.AbstractBeanDefinition#prepareMethodOverrides:验证methodOverrides
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:执行BeanPostProcessor后处理器
四、源码分析
1. 先看加载bean的方法,AbstractBeanFactory#doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1.转换beanName,主要处理别名、以&开头的name
final String beanName = transformedBeanName(name);
Object bean;
// 2.尝试从单例缓存中获取bean实例
Object sharedInstance = getSingleton(beanName);
// 3. 获取bean实例
// 3.1 缓存中已存在bean实例
if (sharedInstance != null && args == null) {
// 省略日志输出代码...
// 从bean实例中获取对象(本章重点,获取实例中的对象)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 缓存中不存在bean实例的情况
else {
// 省略父工厂处理相关代码...
try {
// 省略dependsOn相关代码...
// 3.2 创建单例bean
if (mbd.isSingleton()) {
// 获取单例(本章重点)
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 3.3 创建原型bean实例
else if (mbd.isPrototype()) {
// 省略原型bean创建逻辑...
}
// 3.4 根据scope创建bean实例
else {
// 省略根据scope策略创建bean逻辑...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 省略其他代码.
...
}
可以看到缓存中不存在bean实例时,创建单例bean的逻辑是调用getSingleton()方法完成的,跟进去看下具体逻辑。
2. 准备创建bean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 1. 解析bean对应的Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 2. 验证methodOverride对应的方法是否存在?是否有重载?(重点方法)
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 3. 给BeanPostProcessor一个机会来返回代理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 {
// 4. 创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
可以看到以上有4个步骤:
- 解析beanName对应的Class
- 验证methodOverride对应的方法是否存在?是否有重载? 其中methodOverride指的是bean标签的lookup-method和replaced-method 两个字标签。详见《bean标签的解析之简单子元素的解析》
- 给BeanPostProcessor一个机会返回bean
- 创建bean:doCreateBean()
下面分别看下2和3两个步骤的代码
3. 验证methodOverride
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
if (hasMethodOverrides()) {
// 获取该beanDefinition中的overrides
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
// 循环处理
prepareMethodOverride(mo);
}
}
}
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// class中该方法名的个数
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) {
// 如果该方法名只有一个方法,则证明该方法没有重载,记录在此
mo.setOverloaded(false);
}
}
此步骤主要目的是,验证AbstractBeanDefinition#methodOverrides中的methodName对应的方法情况。校验该bean对应的Class对象是否存在methodName方法,该方法是否有重载。这一切都是为了后面实例化bean做准备。
4. 执行BeanPostProcessor尝试返回bean
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果beanDefinition未被解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 不是自定义的beanDefinition
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 实例化前的后处理器应用
// 如果此处返回bean不为空,则实例化后的beanProcessor继续处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 实例化后的后处理器应用
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// InstantiationAwareBeanPostProcessor类型的beanProcessor才有资格处理
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 实例化之前的后处理
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 实例化之后的后处理
// 拿到实例化前的beanProcessor处理结果,交由实例化后的beanProcessor继续处理
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到doCreateBean()方法之前,可以通过容器中InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法返回bean;在Before有返回的前提下,也可以通过容器中BeanPostProcessor#postProcessAfterInitialization()方法继续处理返回bean。最终的返回结果,决定程序是否执行doCreateBean()方法。