当前位置: 首页 > 科技观察

详细解释一下Spring是如何创建Bean对象的?

时间:2023-03-22 16:25:34 科技观察

上一篇回顾上一篇《Spring如何从IoC容器中获取对象?》整体分析了如何从SpringIoC容器中获取一个bean对象。其逻辑由AbstractBeanFactory#doGetBean方法实现,主要流程如下:本文深入浅出,主要分析如何创建单例(singleton)类型的对象。如何创建单例对象?从流程图可以看出,Spring在获取bean对象时,会先尝试从缓存中获取单例对象。值得注意的是:只有当对象是单例场景时,即scope为单例时才会缓存对象。这其实涉及到所谓的“三级缓存”。为了更容易理解三级缓存,本文先研究bean对象什么时候放入缓存,后面再研究三级缓存。既然能取到,那么缓存中肯定有存放bean对象的地方,那么缓存中的数据从哪里来呢?下面主要分析单例对象是如何创建并放入缓存的。逻辑在AbstractBeanFactory#doGetBean方法中,主要代码如下(创建单例bean对象的代码保留,其他部分暂时忽略):,@NullableClassrequiredType,@NullableObject[]args,booleantypeCheckOnly)throwsBeansException{StringbeanName=transformedBeanName(name);Objectbean;//从缓存中获取单例bean对象ObjectsharedInstance=getSingleton(beanName);//bean对象做缓存中不存在else{//。..try{//GetBeanDefinitionRootBeanDefinitionmbd=getMergedLocalBeanDefinition(beanName);//获取依赖bean对象//如果创建依赖其他对象的bean对象,首先创建依赖对象//...//Createscopeassingleton(Singleton)objectif(mbd.isSingleton()){sharedInstance=getSingleton(beanName,()->{try{returncreateBean(beanName,mbd,args);}catch(BeansExceptionex){//...}});//ProcessFactoryBeanscenebean=getObjectForBeanInstance(sharedInstance,name,beanName,mbd);}//创建一个作用域为原型的对象elseif(mbd.isPrototype()){//...}//创建其他类型的对象else{//...}}catch(BeansExceptionex){//...}}//类型检查返回rn(T)bean;}}其实就是DefaultSingletonBeanRegistry#getSingleton方法,代码如下:publicclassDefaultSingletonBeanRegistryextendsSimpleAliasRegistryimplementsSingletonBeanRegistry{//Singletonbean对象缓存(beanName,bean)privatefinalMapsingletonObjects=newConcurrentHashMap<>(256GetSub,ObjectFactorysingletonFactory){Assert.notNull(beanName,"Beannamemustnotbenull");synchronized(this.singletonObjects){//先从缓存中获取bean对象ObjectsingletonObject=this.singletonObjects.get(beanName);//缓存创建if(singletonObject==null){//...//beforeSingletonCreation(beanName);booleannewSingleton=false;booleanrecordSuppressedExceptions=(this.suppressedExceptions==null);if(recordSuppressedExceptions){this.suppressedExceptions=newLinkedHashSet<>();}try{//创建一个单例对象singletonObject=singletonFactory.getObject();newSingleton=true;}//catch...finally{if(recordSuppressedExceptions){this.suppressedExceptions=null;}//创建单例对象后afterSingletonCreation(beanName);}if(newSingleton){//将对象添加到缓存中addSingleton(beanName,singletonObject);}}//如果缓存中有东西,直接返回singletonObject;}}}getSingleton方法会先从缓存singletonObjects(其实是一个Map)获取bean对象,如果有缓存则直接返回,否则创建成功后会将对象存入缓存。创作逻辑在哪里?代码是通过ObjectFactory#getObject方法创建的。ObjectFactory是一个函数式接口:@FunctionalInterfacepublicinterfaceObjectFactory{TgetObject()throwsBeansException;}这个方法的实现是什么?返回上一层,即getBean方法,看这里:sharedInstance=getSingleton(beanName,()->{try{//创建bean对象returncreateBean(beanName,mbd,args);}catch(BeansExceptionex){//...}});这里使用了lambda表达式,使用以下表达式作为参数:()->{try{//创建一个bean对象returncreateBean(beanName,mbd,args);}catch(BeansExceptionex){//...}}Createabean对象的逻辑就在这个createBean方法中,它在AbstractAutowireCapableBeanFactory类中:publicabstractclassAbstractAutowireCapableBeanFactoryextendsAbstractBeanFactoryimplementsAutowireCapableBeanFactory{@OverrideprotectedObjectcreateBean(StringbeanName,RootBeanDefinitionmbd,@NullableObject[]args)throwsBeanCreationException{RootBeanDefinitionmbdToUse=mbd;ClassresolvedClass=resolveBeanClass(mbd,豆名);如果(resolvedClass!=null&&!mbd.hasBeanClass()&&mbd.getBeanClassName()!=null){mbdToUse=newRootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}//Preparemethodoverrides.try{mbdToUse.prepareMethodOverrides();}//catch...try{//GiveBeanPostProcessorsachancetoreturnaproxyinsteadofthetargetbeaninstance.//这里可能会返回代理对象Objectbean=ResolveBeforeInstantiation(bean,mbdToUse);if(bean!=null){returnbean;}}//catch...try{//创建bean对象ObjectbeanInstance=doCreateBean(beanName,mbdToUse,args);if(logger.isTraceEnabled()){logger.trace("Finishedcreatinginstanceofbean'"+beanName+"'");}returnbeanInstance;}//catch...}}值得注意的是resolveBeforeInstantiation方法其实是和AOP实现相关的,代理对象可能是generatedhereandreturn由于现在主要分析IoC的过程,这里暂时略过,有兴趣的朋友可以自己研究。继续按照这里的主线逻辑。创建bean对象是在doCreateBean方法中实现的,如下:publicabstractclassAbstractAutowireCapableBeanFactoryextendsAbstractBeanFactoryimplementsAutowireCapableBeanFactory{protectedObjectdoCreateBean(StringbeanName,RootBeanDefinitionmbd,@NullableObject[]args)throwsBeanCreationException{//Instantiatethebean.//1.实例化beanBeanWrapperinstanceWrapper=null;if(mbd.isSingleton()){instanceWrapper=this.factoryBeanInstanceCache.remove(beanName);}if(instanceWrapper==null){instanceWrapper=createBeanInstance(beanName,mbd,args);}Objectbean=instanceWrapper.getWrappedInstance();ClassbeanType=instanceWrapper。getWrappedClass();if(beanType!=NullBean.class){mbd.resolvedTargetType=beanType;}//允许后处理器修改合并的beandefinition.synchronized(mbd.postProcessingLock){if(!mbd.postProcessed){try{applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);}//catch...mbd.postProcessed=true;}}booleanearlySingletonExposure=(mbd.isSingleton()&&this.allowCircularReferences&&isSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure){addSingletonFactory(beanName,()->getEarlyBeanReference(beanName,mbd,bean));}//初始化beaninstance.ObjectexposedObject=bean;try{//2.填充属性populateBean(beanName,mbd,instanceWrapper);//3.初始化exposedObject=initializeBean(beanName,exposedObject,mbd);}//catch...if(earlySingletonExposure){ObjectearlySingletonReference=getSingleton(beanName,false);if(earlySingletonReference!=null){如果(exposedObject==bean){exposedObject=earlySingletonReference;}elseif(!this.allowRawInjectionDespiteWrapping&&hasDependentBean(beanName)){String[]dependentBeans=getDependentBeans(beanName);SetactualDependentBeans=newLinkedHashSet<>(dependentBeans.length);for(StringdependentBean:dependentBeans){if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)){actualDependentBeans.add(dependentBean);}}//...}}}//Registerbeanasdisposable.try{registerDisposableBeanIfNecessary(beanName,bean,mbd);}//catch...returnexposedObject;}}注意:Instantiate和Initialize虽然看起来有点像,但不是一回事,前者是“实例化”,后者是“”Initialization”方法看起来有点长,但是主要的只有三个:创建bean对象:createBeanInstance方法填充属性:populateBean方法初始化bean:initializeBean方法这些方法里面其实有很多堆...代码,以及然后对比上面给出的整体流程图:就是这样了,这篇文章是在上一篇文章整体分析的基础上进一步提炼出来的,先说到这里,再继续分析~小结如何从SpringIoC中获取bean对象container?整体流程在上一篇文章分析过,本文在上一篇文章的基础上进一步提炼,主要讨论Spring如何从整体上创建单例bean对象,整体分为三个步骤:C重新创建bean对象。填充bean属性并初始化bean对象。至于这三个步骤是干什么的,且听下一章。

最新推荐
猜你喜欢