5、Spring之Bean生命周期~创建Bean
创建Bean
Spring Bean的生命周期首先会经过扫描,然后回经过合并,合并之后就会通过getBean()方法去获取bean,getBean()方法大致逻辑,先根据判断是单例bean还是原型bean,原型bean直接创建,单例bean会判断单例池中有没有,没有的话调用createBean()方法。而createBean方法也没有真正的执行实例化操作,而是执行啦实例化前操作,废话不多说,直接上代码:
//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
*
* @see #doCreateBean
*/
@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;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 马上就要实例化Bean了,确保beanClass被加载了
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 {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 实例化前
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 {
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()方法并不是直接去创建Bean对象,而是要经过一系列的准备工作,我们开始逐行分析:
- 首先会调用resolveBeanClass()方法,确保Bean对象的class已经被加载;
- prepareMethodOverrides()方法的作用是判断MethodOverrides属性是否存在,存在的话进行方法覆盖,由于配置文件方式使用较少,此方法不展示细说,感兴趣的小伙伴可以自行查阅相关资料;
- 再往下就到啦比较重要的实例化前,调用resolveBeforeInstantiation()方法,执行初始化前操作;
- 如果实例化前这一步有返回值,会直接返回,不走后续的实例化、依赖注入、初始化前,直接跳到初始化这一步,执行AOP操作;
- 调用doCreateBean()方法执行;由于doCreateBean()方法逻辑比较多,请移步至《Spring之Bean生命周期~创建Bean(2)》
resolveBeanClass()方法
resolveBeanClass()方法详解
/**
* Resolve the bean class for the specified bean definition,
* resolving a bean class name into a Class reference (if necessary)
* and storing the resolved Class in the bean definition for further use.
*
* @param mbd the merged bean definition to determine the class for
* @param beanName the name of the bean (for error handling purposes)
* @param typesToMatch the types to match in case of internal type matching purposes
* (also signals that the returned {@code Class} will never be exposed to application code)
* @return the resolved bean class (or {@code null} if none)
* @throws CannotLoadBeanClassException if we failed to load the class
*/
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 如果beanClass被加载了
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 如果beanClass没有被加载
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
} else {
return doResolveBeanClass(mbd, typesToMatch);
}
} catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
} catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
} catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
通过上述代码我们可以看到:
- 如果beanClass被加载过,直接返回;
- 如果还没有被加载,调用doResolveBeanClass()方法加载beanClass,并且拿到类加载器;
- 返回createBean()方法;
doResolveBeanClass()方法
doResolveBeanClass()方法详解
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
// When just doing type checks (i.e. not creating an actual instance yet),
// use the specified temporary class loader (e.g. in a weaving scenario).
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
}
}
String className = mbd.getBeanClassName();
if (className != null) {
// 解析Spring表达式,有可能直接返回了一个Class对象
Object evaluated = evaluateBeanDefinitionString(className, mbd);
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
} else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
} else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
return dynamicLoader.loadClass(className);
} catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
return ClassUtils.forName(className, dynamicLoader);
}
}
// Resolve regularly, caching the result in the BeanDefinition...
return mbd.resolveBeanClass(beanClassLoader);
}
通过上诉代码,我们可以看到:
- 优先返回当前线程中的ClassLoader;
- 线程中类加载器为null的情况下,返回ClassUtils类的类加载器;
- 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器;
- 返回resolveBeanClass()方法;
resolveBeforeInstantiation()方法
resolveBeforeInstantiation()方法详解
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
*
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@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.
// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
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;
}
通过上述方法,我们可以看到,首先会判断Bean对象是否实现了InstantiationAwareBeanPostProcessor接口,如果实现了InstantiationAwareBeanPostProcessor接口,会调用它的postProcessBeforeInstantiation方法,返回postProcessBeforeInstantiation方法的执行结果;
返回createBean()方法;