5、Spring之Bean生命周期~创建Bean
- 创建Bean
- resolveBeanClass()方法
- doResolveBeanClass()方法
- resolveBeforeInstantiation()方法
创建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()方法;