spring面试必问bean对象的生命周期
之前简单记录了下springBean的生命周期,最近翻开来看了下,发现自己遗漏了很多细节,很多点都衔接不上今天重新翻看《spring揭秘》,查资料,补了许多细节。希望能够让自己和大家更容易看懂吧Bean的生命周期的完全实现需要两个阶段容器的启动bean的实例化过程(涵盖了bean生命周期的大部分)
容器的完全实现
bean实例化过程容器启动阶段重点是收集到元信息配置信息,即创建bean需要的信息(beanDefinition)通过BeanDefinitionReader,读取到beanDefinition信息,再通过beanDefinitionRegistry,将BeanDefinition注册到其里面这是PropertiesBeanDefinitionReader把从properties文件读取到的配置信息,通过BeanDefinitionRegistry注册BeanDefinition的过程AbstractBeanDefinitionbdBeanDefinitionReaderUtils。createBeanDefinition(parent,className,getBeanClassLoader());bd。setScope(scope);作用域默认singletonbd。setAbstract(isAbstract);是否是抽象默认false如果是抽象的,容器不会实例化bean,而是将beanDefinition信息作为其子类使用bd。setLazyInit(lazyInit);懒加载默认false如果是false,容器一启动就会加载beanbd。setConstructorArgumentValues(cas);构造参数bd。setPropertyValues(pvs);属性信息getRegistry()。registerBeanDefinition(beanName,bd);注册BeandefinitionBeanDefinitionReader有多种,包括:
PropertiesBeanDefinitionReader读取Properties配置文件
GroovyBeanDefinitionReader读取Groovy配置文件
XmlBeanDefinitionReader读取Xml配置文件bean实例化前对beanDefinition做出自定义修改
BeanFactoryPostProcessor实例化bean之前,可以允许修改beanDefinition信息,下面是spring默认实现的BeanFactoryPostProcessor类:PropertyPlaceholderConfigurer允许我们在XML配置文件中使用占位符(PlaceHolder),并将这些占位符所代表的资源单独配置到简单的properties文件中来加载PropertyOverrideConfigurer覆盖对象的属性值我们可以自己实现BeanFactoryPostProcessor依赖注入beanFactory,修改beanDefinition信息bean实例化阶段
doCreateBean源码方法(下面仅对beanFactory容器做解析,applicationContext容器其实大同小异)Actuallycreatethespecifiedbean。Precreationprocessinghasalreadyhappenedatthispoint,e。g。checking{codepostProcessBeforeInstantiation}callbacks。pDifferentiatesbetweendefaultbeaninstantiation,useofafactorymethod,andautowiringaconstructor。parambeanNamethenameofthebeanparammbdthemergedbeandefinitionforthebeanparamargsexplicitargumentstouseforconstructororfactorymethodinvocationreturnanewinstanceofthebeanthrowsBeanCreationExceptionifthebeancouldnotbecreatedseeinstantiateBeanseeinstantiateUsingFactoryMethodseeautowireConstructorprotectedObjectdoCreateBean(StringbeanName,RootBeanDefinitionmbd,NullableObject〔〕args)throwsBeanCreationException{Instantiatethebean。BeanWrapperinstanceWrappernull;if(mbd。isSingleton()){instanceWrapperthis。factoryBeanInstanceCache。remove(beanName);}if(instanceWrappernull){instanceWrappercreateBeanInstance(beanName,mbd,args);}实例化beanObjectbeaninstanceWrapper。getWrappedInstance();Classlt;?beanTypeinstanceWrapper。getWrappedClass();if(beanType!NullBean。class){mbd。resolvedTargetTypebeanType;}Allowpostprocessorstomodifythemergedbeandefinition。synchronized(mbd。postProcessingLock){if(!mbd。postProcessed){try{applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);}catch(Throwableex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Postprocessingofmergedbeandefinitionfailed,ex);}mbd。postProcessedtrue;}}EagerlycachesingletonstobeabletoresolvecircularreferencesevenwhentriggeredbylifecycleinterfaceslikeBeanFactoryAware。booleanearlySingletonExposure(mbd。isSingleton()this。allowCircularReferencesisSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure){if(logger。isTraceEnabled()){logger。trace(EagerlycachingbeanbeanNametoallowforresolvingpotentialcircularreferences);}addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));}Initializethebeaninstance。ObjectexposedObjectbean;try{填充bean对象属性populateBean(beanName,mbd,instanceWrapper);初始化beanexposedObjectinitializeBean(beanName,exposedObject,mbd);}catch(Throwableex){if(exinstanceofBeanCreationExceptionbeanName。equals(((BeanCreationException)ex)。getBeanName())){throw(BeanCreationException)ex;}else{thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Initializationofbeanfailed,ex);}}if(earlySingletonExposure){ObjectearlySingletonReferencegetSingleton(beanName,false);if(earlySingletonReference!null){if(exposedObjectbean){exposedObjectearlySingletonReference;}elseif(!this。allowRawInjectionDespiteWrappinghasDependentBean(beanName)){String〔〕dependentBeansgetDependentBeans(beanName);SetStringactualDependentBeansnewLinkedHashSet(dependentBeans。length);for(StringdependentBean:dependentBeans){if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)){actualDependentBeans。add(dependentBean);}}if(!actualDependentBeans。isEmpty()){thrownewBeanCurrentlyInCreationException(beanName,BeanwithnamebeanNamehasbeeninjectedintootherbeans〔StringUtils。collectionToCommaDelimitedString(actualDependentBeans)〕initsrawversionaspartofacircularreference,buthaseventuallybeenwrapped。Thismeansthatsaidotherbeansdonotusethefinalversionofthebean。ThisisoftentheresultofovereagertypematchingconsiderusinggetBeanNamesForTypewiththeallowEagerInitflagturnedoff,forexample。);}}}}Registerbeanasdisposable。try{检查是否实现DisposableBean接口,有的话注册销毁回调方法registerDisposableBeanIfNecessary(beanName,bean,mbd);}catch(BeanDefinitionValidationExceptionex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Invaliddestructionsignature,ex);}returnexposedObject;}首先第一步,调用createBeanInstance方法,利用反射调用类的构造方法,实例化bean,返回beanWrapper对象,再调用getWrappedInstance方法得到实例化的bean,beanWrapper对象具有获取对象属性的功能,所以可以调用populateBean用来实现属性填充。
20230225155458开始实例化bean之前,会检查bean有没有实现过Aware接口,如果有则实现。AbstractAutowireCapableBeanFactory类中的initializeBean方法privatevoidinvokeAwareMethods(StringbeanName,Objectbean){if(beaninstanceofAware){如果Spring容器检测到当前对象实例实现了该接口,会将该对象实例的bean定义对应的beanName设置到当前对象实例。if(beaninstanceofBeanNameAware){((BeanNameAware)bean)。setBeanName(beanName);}如果容器检测到当前对象实例实现了该接口,会将对应加载当前bean的Classloader注入当前对象实例。默认会使用加载org。springframework。util。ClassUtils类的Classloaderif(beaninstanceofBeanClassLoaderAware){ClassLoaderbclgetBeanClassLoader();if(bcl!null){((BeanClassLoaderAware)bean)。setBeanClassLoader(bcl);}}if(beaninstanceofBeanFactoryAware){((BeanFactoryAware)bean)。setBeanFactory(AbstractAutowireCapableBeanFactory。this);}以上几个Aware接口只是针对BeanFactory类型的容器而言}}
对于ApplicationContext类型容器,会额外实现几个Aware接口BeanPostProcessor阶段
BeanPostProcessor的概念容易与BeanFactoryPostProcessor的概念混淆。但只要记住BeanPostProcessor是存在于对象实例化阶段,而BeanFactoryPostProcessor则是存在于容器启动阶段,这两个概念就比较容易区分了。
BeanPostProcessor有两个需要子类实现的方法publicinterfaceBeanPostProcessor{调用bean的init方法之前做的前置处理NullabledefaultObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{returnbean;}调用bean的init方法之后做的前置处理NullabledefaultObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{returnbean;}}
在initializeBean方法内可以看到BeanPostProcessor的调用顺序protectedObjectinitializeBean(StringbeanName,Objectbean,NullableRootBeanDefinitionmbd){if(System。getSecurityManager()!null){AccessController。doPrivileged((PrivilegedActionObject)(){invokeAwareMethods(beanName,bean);returnnull;},getAccessControlContext());}else{调用实现了Aware接口的对象方法invokeAwareMethods(beanName,bean);}ObjectwrappedBeanbean;if(mbdnull!mbd。isSynthetic()){BeanPostProcessor前置处理wrappedBeanapplyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);}try{调用bean的init方法invokeInitMethods(beanName,wrappedBean,mbd);}catch(Throwableex){thrownewBeanCreationException((mbd!null?mbd。getResourceDescription():null),beanName,Invocationofinitmethodfailed,ex);}if(mbdnull!mbd。isSynthetic()){BeanPostProcessor后置处理wrappedBeanapplyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);}returnwrappedBean;}
注意:applcationContext容器中实现BeanPostProcessor接口的postProcessBeforeInitialization中,会对实现了Aware接口的bean进行invoke调用。这里和BeanFactory有些不同,BeanFactory是在BeanPostProcessor之前实现的InitializingBean和initmethod
这两个方法都是在invokeInitMethods方法里调用,InitializingBean接口需要实现afterPropertiesSet方法允许bean实例在设置完所有bean属性后执行其整体配置验证和最终初始化。initmethod,对于用户来说可以自定义方法的名称,也可以统一设置所有对象的initMethod比较灵活,避免修改代码,耦合性低。DisposableBean与destroymethod
DisposableBean接口,子类需要实现destroy方法,来销毁对象,只适用于单例对象,不是单例的话,需要交给调用者自己销毁。destroymethod注册销毁函数,作用和destroy方法同理总结
本文主要讲了bean在BeanFacotry容器的生命周期,applicationContext容器稍微提了几点不同,applicationContext容器增加更多的特性,像事件发布监听,国际化信息支持等。bean的生命周期主要涉及到容器的加载和bean的实例化。
容器的加载:加载资源文件到beanDefinition(元信息)调用实现了BeanFactoryPostProcessor接口的方法,可以对beanDefinition进行修改。
bean的实例化:利用反射beanDefinition元信息实例化得到对象populateBean方法填充属性检验对象是否实现过Aware接口,有则调用其实现如果对象有实现BeanPostProcessor接口,需要先实现前置方法调用InitializingBean和initmethod方法如果有实现或标记的话再调用BeanPostProcessor接口的后置方法最后查看对象是否实现DisposableBean与destroymethod来销毁bean(DisposableBean接口只针对单例bean)资料:
《spring揭秘》王福强