0


Spring之Bean创建过程

1. 前言

Spring提供了xml、注解、JavaConfig多种方式来配置bean,不论何种方式,Spring最终都会将bean封装成BeanDefinition对象,Spring创建bean的依据也是通过BeanDefinition来完成的。
当我们调用

getBean()

方法获取bean实例时,不管是单例bean还是原型bean,首次调用时容器内都不存在可用的bean实例,这时就不得不去创建bean了,我们分析下Spring创建bean的过程。

2. Bean创建概览

Bean生命周期.jpg
Spring Bean的创建过程是非常复杂的,但是整体流程又是清晰的。创建bean的入口函数在

AbstractAutowireCapableBeanFactory#createBean()

,Spring首先会触发一个扩展点

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()

,如果扩展点返回了可用的bean,这里会进行短路操作,Spring将不再去实例化目标bean,这样做的好处是,扩展点可以在这里返回一个代理对象去避免目标bean被实例化。
如果扩展点没有返回可用的bean对象,Spring会自己去实例化bean,实例化bean的方式有三种,取决于BeanDefinition的配置。Bean实例化完了之后,Spring会通过扩展点的方式来收集Bean的注解属性和方法,比如:@Autowired、@Value、init-method等等,信息收集完毕会通过

populateBean()

方法对bean进行属性填充,其实就是注入依赖。属性填充完毕,紧接着会对bean进行初始化,触发bean实现的各种Aware接口,生命周期方法,以及BeanPostProcessor扩展点。
以上执行完毕后,此时的bean就已经是一个可用的bean了,可以直接返回了。但是,bean可能还会有destroy-method方法,需要在bean销毁时被调用,所以最后还需要把这一类bean暂存到Map容器中,以便销毁时触发。

3. InstantiationAwareBeanPostProcessor

根据beanName创建bean,首先需要知道bean对应的class。解析class有2种方式,如果mbd存在BeanClass就直接用,否则根据BeanClassName加载class。

/**
* 解析BeanClass
* 1.存在BeanClass
* 2.根据BeanClassName加载Class
*/Class<?> resolvedClass =resolveBeanClass(mbd, beanName);

紧接着准备MethodOverrides,因为Spring支持

lookup-method

replace-method

功能,针对这两类方法Spring统一保存在MethodOverrides里面,如果bean存在MethodOverrides,则需要创建代理对象来增强。
这里的准备阶段,其实是解析MethodOverride是否存在重载方法,如果不存在重载方法,会将overloaded设为false,增强调用时就不用再根据参数类型去判断该调用哪个重载方法了。

/**
 * 准备重写方法,解析是否有重载方法
 * 1.lookup-method
 * 2.replace-method
 * 如果存在MethodOverride,则创建代理对象
 */try{
    mbdToUse.prepareMethodOverrides();}catch(BeanDefinitionValidationException ex){thrownewBeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName,"Validation of method overrides failed", ex);}

然后Spring触发扩展点

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()

,如果扩展点返回了可用的bean,Spring将不再对目标bean进行实例化。这里你可以返回一个代理对象,然后自己决定什么时候实例化目标bean。

try{/**
     * 触发InstantiationAwareBeanPostProcessor扩展
     * 允许它返回代理对象,来避免目标Bean实例化
     * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)
     */Object bean =resolveBeforeInstantiation(beanName, mbdToUse);if(bean !=null){/**
         * 如果InstantiationAwareBeanPostProcessor返回了代理对象,则不再实例化目标Bean,短路操作
         */return bean;}}catch(Throwable ex){thrownewBeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}
resolveBeforeInstantiation()

其实就是从容器中取出所有的InstantiationAwareBeanPostProcessor实现类,然后依次调用

postProcessBeforeInstantiation()

方法。如果扩展点返回了bean对象,紧接着会马上触发

postProcessAfterInitialization()

方法,跳过目标bean的实例化。

protectedObjectresolveBeforeInstantiation(String beanName,RootBeanDefinition mbd){Object bean =null;if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)){if(!mbd.isSynthetic()&&hasInstantiationAwareBeanPostProcessors()){Class<?> targetType =determineTargetType(beanName, mbd);if(targetType !=null){// 应用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation处理器
                bean =applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if(bean !=null){/**
                     * 如果扩展点返回了可用bean,不再实例化目标bean,紧接着应用after处理器
                     * 应用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation处理器
                     */
                    bean =applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}
        mbd.beforeInstantiationResolved =(bean !=null);}return bean;}

4. createBeanInstance

如果InstantiationAwareBeanPostProcessor扩展点没有返回可用bean,Spring会对目标bean实例化,紧接着调用

doCreateBean()

方法。
实例化bean的方法是

AbstractAutowireCapableBeanFactory#createBeanInstance()

,实例化bean的方式有三种:

  • 如果RootBeanDefinition提供了instanceSupplier方法,则直接调用instanceSupplier方法来生成bean对象,避免反射实例化bean的性能消耗。
  • 如果是@Bean方法声明的bean,Spring会从容器中找到factoryBeanName对应的工厂bean,然后反射调用factoryMethodName来创建bean。
  • 通过构造函数实例化。
protectedBeanWrappercreateBeanInstance(String beanName,RootBeanDefinition mbd,@NullableObject[] args){Class<?> beanClass =resolveBeanClass(mbd, beanName);if(beanClass !=null&&!Modifier.isPublic(beanClass.getModifiers())&&!mbd.isNonPublicAccessAllowed()){thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: "+ beanClass.getName());}Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier !=null){returnobtainFromSupplier(instanceSupplier, beanName);}/**
     * 如果是@Bean方法声明的bean,则调用工厂方法来生成bean
     * 从容器中取出factoryBean,反射调用@Bean方法生成bean
     */if(mbd.getFactoryMethodName()!=null){returninstantiateUsingFactoryMethod(beanName, mbd, args);}boolean resolved =false;boolean autowireNecessary =false;if(args ==null){synchronized(mbd.constructorArgumentLock){/*
                一个类有多个构造函数,每个构造函数都有不同的参数,
                所以需要根据参数锁定构造函数并进行初始化
             */if(mbd.resolvedConstructorOrFactoryMethod !=null){
                resolved =true;
                autowireNecessary = mbd.constructorArgumentsResolved;}}}// 如果已经解析过则使用解析好的构造函数 , 不需要再次锁定if(resolved){if(autowireNecessary){// 构造函数注入returnautowireConstructor(beanName, mbd,null,null);}else{// 无参构造函数returninstantiateBean(beanName, mbd);}}// 根据参数解析构造函数Constructor<?>[] ctors =determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors !=null|| mbd.getResolvedAutowireMode()==AUTOWIRE_CONSTRUCTOR||
            mbd.hasConstructorArgumentValues()||!ObjectUtils.isEmpty(args)){//构造函数自动注入returnautowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?
    ctors = mbd.getPreferredConstructors();if(ctors !=null){returnautowireConstructor(beanName, mbd, ctors,null);}// 无需特殊处理:只需使用无参构造函数。returninstantiateBean(beanName, mbd);}

5. MergedBeanDefinitionPostProcessor

通过

**createBeanInstance()**

方法实例化的bean只是一个不可用的bean对象,因为这个时候bean的属性还没有填充,依赖也没有注入,初始化方法也没有被调用,后置处理器也还没有执行。
紧接着,Spring会对bean做一些信息收集,收集的信息包括@Autowired、@Value、@Resource等注解,init-method、destroy-method方法等,将这些信息封装成Member对象,存放到RootBeanDefinition的externallyManagedConfigMembers属性里。
收集工作是通过扩展点

MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()

进行的,Spring内置了多个实现类来收集信息,通过名字基本就能看出来它们要收集哪些信息。

  • CommonAnnotationBeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • InitDestroyAnnotationBeanPostProcessor
synchronized(mbd.postProcessingLock){if(!mbd.postProcessed){try{/**
             * 触发扩展点
             * 解析bean的 @Autowired @Value @Resource注解
             * init destory-method方法
             * 存放到BD的externallyManagedConfigMembers中
             * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Class, java.lang.String)
             */applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch(Throwable ex){thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}
        mbd.postProcessed =true;}}

6. SmartInstantiationAwareBeanPostProcessor

Bean的信息收集完毕,还有一个问题需要解决。Spring是允许Bean之间存在循环依赖的,比如BeanA有一个属性BeanB,BeanB也有一个属性BeanA,两者互相依赖对方。Spring创建BeanA时发现它依赖BeanB,就会去创建BeanB,创建BeanB时又发现它依赖BeanA,此时又会去创建BeanA,循环依赖就此产生。为了打破这个死循环,Spring的解决方案是,不等BeanA完全创建好,就提前暴露到缓存中,这样在创建BeanB时就可以直接依赖这个半成品BeanA了,循环就此打破。
如果允许提前暴露bean,那么Spring还会触发一个扩展点

SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference()

来获得提前暴露bean的引用,默认是直接原样返回bean。

/**
 * 这个时候bean还没初始化,是否要提前暴露Bean?以便循环依赖
 * 条件:单例 & 允许循环依赖 & bean正在创建中
 */boolean earlySingletonExposure =(mbd.isSingleton()&&this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure){if(logger.isTraceEnabled()){
        logger.trace("Eagerly caching bean '"+ beanName +"' to allow for resolving potential circular references");}/**
     * 加入到singletonFactories
     */addSingletonFactory(beanName,/**
             * 获取提前暴露Bean的引用,默认原样返回bean
             * 触发扩展点,AOP在这里将advice织入bean中
             * @see SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(java.lang.Object, java.lang.String)
             */()->getEarlyBeanReference(beanName, mbd, bean));}

7. populateBean

bean实例生成了,bean的信息也收集完毕了,接下来就是对bean进行属性填充了,方法是

populateBean()


Spring此时又会触发一个扩展点

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()

,返回值代表是否要继续填充bean,默认返回true。

/**
 * 触发扩展点,返回值代表是否要继续填充bean
 * @see InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(java.lang.Object, java.lang.String)
 */boolean continueWithPropertyPopulation =true;if(!mbd.isSynthetic()&&hasInstantiationAwareBeanPostProcessors()){for(BeanPostProcessor bp :getBeanPostProcessors()){if(bp instanceofInstantiationAwareBeanPostProcessor){InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)){
                continueWithPropertyPopulation =false;break;}}}}if(!continueWithPropertyPopulation){return;}

如果需要继续填充bean,则通过

InstantiationAwareBeanPostProcessor#postProcessProperties()

扩展点来完成的bean的填充。执行完这一步,Bean的属性会完成填充,依赖也会被注入。

/**
 * 触发扩展点,这里会注入@Autowired、@Resource、@Value等属性
 * @see InstantiationAwareBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String) InstantiationAwareBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String)
 * @see InstantiationAwareBeanPostProcessor#postProcessPropertyValues(org.springframework.beans.PropertyValues, java.beans.PropertyDescriptor[], java.lang.Object, java.lang.String)
 */PropertyDescriptor[] filteredPds =null;if(hasInstAwareBpps){if(pvs ==null){
        pvs = mbd.getPropertyValues();}for(BeanPostProcessor bp :getBeanPostProcessors()){if(bp instanceofInstantiationAwareBeanPostProcessor){InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if(pvsToUse ==null){if(filteredPds ==null){
                    filteredPds =filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}// 对所有需要依赖检查的属性进行后处理
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if(pvsToUse ==null){return;}}
            pvs = pvsToUse;}}}

8. initializeBean

属性填充,依赖注入完,接下来就是bean的初始化。
首先会调用

invokeAwareMethods()

方法来触发Bean实现的各类Aware接口。

privatevoidinvokeAwareMethods(finalString beanName,finalObject bean){if(bean instanceofAware){if(bean instanceofBeanNameAware){((BeanNameAware) bean).setBeanName(beanName);}if(bean instanceofBeanClassLoaderAware){ClassLoader bcl =getBeanClassLoader();if(bcl !=null){((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if(bean instanceofBeanFactoryAware){((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}

然后触发扩展点

BeanPostProcessor#postProcessBeforeInitialization()

Object wrappedBean = bean;if(mbd ==null||!mbd.isSynthetic()){/**
     * 触发扩展点
     * @see BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
     */
    wrappedBean =applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}

如果bean实现了InitializingBean接口,Spring紧接着会触发

InitializingBean#afterPropertiesSet()

扩展点,再执行init-method。

protectedvoidinvokeInitMethods(String beanName,finalObject bean,@NullableRootBeanDefinition mbd)throwsThrowable{//判断该bean 如果实现了InitializingBean接口,则调用bean的afterPropertiesSet方法boolean isInitializingBean =(bean instanceofInitializingBean);// 执行afterPropertiesSet方法if(isInitializingBean &&(mbd ==null||!mbd.isExternallyManagedInitMethod("afterPropertiesSet"))){if(logger.isTraceEnabled()){
                logger.trace("Invoking afterPropertiesSet() on bean with name '"+ beanName +"'");}if(System.getSecurityManager()!=null){try{AccessController.doPrivileged((PrivilegedExceptionAction<Object>)()->{((InitializingBean) bean).afterPropertiesSet();returnnull;},getAccessControlContext());}catch(PrivilegedActionException pae){throw pae.getException();}}else{((InitializingBean) bean).afterPropertiesSet();}}// 执行initMethod方法if(mbd !=null&& bean.getClass()!=NullBean.class){String initMethodName = mbd.getInitMethodName();//判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-methodif(StringUtils.hasLength(initMethodName)&&!(isInitializingBean &&"afterPropertiesSet".equals(initMethodName))&&!mbd.isExternallyManagedInitMethod(initMethodName)){//调用init-method方法中指定的方法, 是通过反射实现invokeCustomInitMethod(beanName, bean, mbd);}}}

initMethods执行完毕,接着触发

BeanPostProcessor#postProcessAfterInitialization()

扩展点对bean做最后的扩展。

if(mbd ==null||!mbd.isSynthetic()){/**
     * 触发扩展点
     * @see BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
     */
    wrappedBean =applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;

9. registerDisposableBean

到此为止,bean就创建完毕了,是一个完整的可用的bean了。最后一步,是判断bean是否存在destroy-method,如果有还需要把bean注册到Map容器中,以便bean销毁时调用。

protectedvoidregisterDisposableBeanIfNecessary(String beanName,Object bean,RootBeanDefinition mbd){AccessControlContext acc =(System.getSecurityManager()!=null?getAccessControlContext():null);if(!mbd.isPrototype()&&requiresDestruction(bean, mbd)){if(mbd.isSingleton()){registerDisposableBean(beanName,newDisposableBeanAdapter(bean, beanName, mbd,getBeanPostProcessors(), acc));}else{Scope scope =this.scopes.get(mbd.getScope());if(scope ==null){thrownewIllegalStateException("No Scope registered for scope name '"+ mbd.getScope()+"'");}
            scope.registerDestructionCallback(beanName,newDisposableBeanAdapter(bean, beanName, mbd,getBeanPostProcessors(), acc));}}}
标签: spring java spring boot

本文转载自: https://blog.csdn.net/qq_32099833/article/details/128499937
版权归原作者 程序员小潘 所有, 如有侵权,请联系我们删除。

“Spring之Bean创建过程”的评论:

还没有评论