应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

源码深度解析之SpringIOC

  1。基础知识1。1什么是SpringIOC?
  IOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。
  传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试。
  有了IOC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,便于测试和功能复用,整个体系结构更加灵活。
  理解IOC的关键是要明确谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了,我们浅析一下:谁控制谁,控制什么:传统JavaSE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;IOC是有专门一个容器来创建这些对象,即由IOC容器来控制对象的创建;谁控制谁?当然是IOC容器控制了对象;控制什么?主要控制了外部资源获取。为何反转,哪些方面反转:传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。1。2容器创建过程
  在看源码之前,首先搞清楚SpringIOC容器的创建过程,然后再深入源码。
  IOC容器如婚姻介绍所:男人A要求需要一个女人,中介从婚姻介绍所根据男人A给他介绍了如花;男人B要求介绍一个肤白貌美大长腿,中介从婚姻介绍所根据男人B给他介绍了女神。
  从婚姻介绍所的例子可以大概知道SpringIOC是存储、定制、管理等功能的各种定制化的bean对象容器,下图是SpringIOC容器创建基本流程。
  2。核心知识2。1相关对象2。1。1ApplicationContext
  ApplicationContext接口是BeanFactory的子接口,也被称为Spring上下文,与BeanFactory一样,可以加载配置文件中定义的bean,并进行管理。
  它还加强了企业所需要的功能,如从属性文件中解析文本信息和将事件传递给所有指定的监视器,下图是ApplicationContext接口的继承关系。
  ApplicationContext接口主要的5个作用如表所示:
  2。1。2BeanDefinitionReader示例ClassPathXmlApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);
  配置文件解析器,如将配置文件中的bean信息解析成对应的BeanDefinition对象。
  xml文件解析使用是就是BeanDefinitionReader实现类XmlBeanDefinitionReader。2。1。3BeanFactoryPostProcessor
  可以修改Spring上下文中BeanDefinition信息。
  如下图BeanFactoryPostProcessor的子类PropertySourcesPlaceholderConfigurer的作用可以为数据库连接池{}占位符赋值等等。
  2。1。4BeanFactory
  是所有Bean容器的根接口,定义了spring容器基本方法。
  如使用getBean(beanName,Class)获取对象。
  2。2源码核心流程
  容器初始化的核心源码,都在refresh()方法中:publicvoidrefresh()throwsBeansException,IllegalStateException{synchronized(this。startupShutdownMonitor){1:准备刷新上下文环境prepareRefresh();2:获取初始化Bean工厂ConfigurableListableBeanFactorybeanFactoryobtainFreshBeanFactory();3:对bean工厂进行填充属性prepareBeanFactory(beanFactory);try{4:Spring开放接口留给子类去实现该接口postProcessBeanFactory(beanFactory);5:调用我们的bean工厂的后置处理器invokeBeanFactoryPostProcessors(beanFactory);6:注册我们bean后置处理器registerBeanPostProcessors(beanFactory);7:初始化国际化资源处理器initMessageSource();8:初始化事件多播器initApplicationEventMulticaster();9:这个方法同样也是留个子类实现,其中springboot也是从这个方法进行tomcat的启动onRefresh();10:把我们的事件监听器注册到多播器上registerListeners();11:实例化所有的非懒加载的单实例beanfinishBeanFactoryInitialization(beanFactory);12:最后刷新容器发布刷新事件(Springcloudeureka也是从这里启动的)finishRefresh();}catch(BeansExceptionex){if(logger。isWarnEnabled()){logger。warn(Exceptionencounteredduringcontextinitializationcancellingrefreshattempt:ex);}Destroyalreadycreatedsingletonstoavoiddanglingresources。destroyBeans();Resetactiveflag。cancelRefresh(ex);Propagateexceptiontocaller。throwex;}finally{ResetcommonintrospectioncachesinSpringscore,sincewemightnoteverneedmetadataforsingletonbeansanymore。。。resetCommonCaches();}}}
  什么,内容不够精炼?那我再给大家上一个牛逼的思维导图:
  3。源码解析
  下面主要对refresh()的12个流程进行讲解。3。1prepareRefresh()
  准备刷新上下文环境:protectedvoidprepareRefresh(){Switchtoactive。this。startupDateSystem。currentTimeMillis();this。closed。set(false);this。active。set(true);if(logger。isInfoEnabled()){logger。info(Refreshingthis);}初始化上下文环境initPropertySources();用来校验我们容器启动必须依赖的环境变量的值getEnvironment()。validateRequiredProperties();创建一个早期事件监听器对象if(this。earlyApplicationListenersnull){this。earlyApplicationListenersnewLinkedHashSet(this。applicationListeners);}else{Resetlocalapplicationlistenerstoprerefreshstate。this。applicationListeners。clear();this。applicationListeners。addAll(this。earlyApplicationListeners);}创建一个容器用于保存早期待发布的事件集合什么是早期事件了?就是我们的事件监听器还没有注册到事件多播器上的时候都称为早期事件this。earlyApplicationEventsnewLinkedHashSet();}3。2ConfigurableListableBeanFactory()
  获取初始化的Bean的工厂:protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){刷新bean工厂()refreshBeanFactory();返回之前容器准备工作的时候创建的的bean工厂也就是DefaultListableBeanFactory(很重要)ConfigurableListableBeanFactorybeanFactorygetBeanFactory();if(logger。isDebugEnabled()){logger。debug(BeanfactoryforgetDisplayName():beanFactory);}returnbeanFactory;}protectedfinalvoidrefreshBeanFactory()throwsIllegalStateException{由于BeanFactory只能刷新一次,多线程情况下可能导致线程安全问题,所有使用cas原子操作来保证if(!this。refreshed。compareAndSet(false,true)){thrownewIllegalStateException(GenericApplicationContextdoesnotsupportmultiplerefreshattempts:justcallrefreshonce);}指定Bean工厂的序列化Idthis。beanFactory。setSerializationId(getId());}3。3prepareBeanFactory()
  对Bean工厂进行填充属性:protectedvoidprepareBeanFactory(ConfigurableListableBeanFactorybeanFactory){设置bean工厂的类加载器为当前application应用上下文的加载器beanFactory。setBeanClassLoader(getClassLoader());为bean工厂设置SPEL表达式解析器对象StandardBeanExpressionResolverbeanFactory。setBeanExpressionResolver(newStandardBeanExpressionResolver(beanFactory。getBeanClassLoader()));为我们的bean工厂设置了一个propertyEditor属性资源编辑器对象(用于后面的给bean对象赋值使用)beanFactory。addPropertyEditorRegistrar(newResourceEditorRegistrar(this,getEnvironment()));注册ApplicationContextAwareProcessor后置处理器用来处理ApplicationContextAware接口的回调方法beanFactory。addBeanPostProcessor(newApplicationContextAwareProcessor(this));当Spring将ApplicationContextAwareProcessor注册后,那么在invokeAwarelnterfaces方法中调用的Aware类已经不是普通的bean了,如ResourceLoaderAware、ApplicationEventPublisherAware、ApplicationContextAware等,那么当然需要在Spring做bean的依赖注入的时候忽略它们。这个就是ignoreDependencyInterface的作用beanFactory。ignoreDependencyInterface(EnvironmentAware。class);beanFactory。ignoreDependencyInterface(EmbeddedValueResolverAware。class);beanFactory。ignoreDependencyInterface(ResourceLoaderAware。class);beanFactory。ignoreDependencyInterface(ApplicationEventPublisherAware。class);beanFactory。ignoreDependencyInterface(MessageSourceAware。class);beanFactory。ignoreDependencyInterface(ApplicationContextAware。class);注册了依赖解析,例如当注册BeanFactory。class的解析依赖后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。beanFactory。registerResolvableDependency(BeanFactory。class,beanFactory);beanFactory。registerResolvableDependency(ResourceLoader。class,this);beanFactory。registerResolvableDependency(ApplicationEventPublisher。class,this);beanFactory。registerResolvableDependency(ApplicationContext。class,this);注册了一个事件监听器探测器后置处理器接口beanFactory。addBeanPostProcessor(newApplicationListenerDetector(this));if(beanFactory。containsBean(LOADTIMEWEAVERBEANNAME)){beanFactory。addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory));SetatemporaryClassLoaderfortypematching。beanFactory。setTempClassLoader(newContextTypeMatchClassLoader(beanFactory。getBeanClassLoader()));}if(!beanFactory。containsLocalBean(ENVIRONMENTBEANNAME)){beanFactory。registerSingleton(ENVIRONMENTBEANNAME,getEnvironment());}if(!beanFactory。containsLocalBean(SYSTEMPROPERTIESBEANNAME)){beanFactory。registerSingleton(SYSTEMPROPERTIESBEANNAME,getEnvironment()。getSystemProperties());}if(!beanFactory。containsLocalBean(SYSTEMENVIRONMENTBEANNAME)){beanFactory。registerSingleton(SYSTEMENVIRONMENTBEANNAME,getEnvironment()。getSystemEnvironment());}}3。4postProcessBeanFactory()
  Spring开放接口留给子类去实现该接口,主要用来改变BeanFactory。
  比如给BeanFactory添加一些自己的BeanPostProcessor(Bean的后置处理器)3。5invokeBeanFactoryPostProcessors()
  调用我们的bean工厂的后置处理器,里面逻辑非常复杂,需要的同学可以和我联系,有详细讲解,就不扩展了。3。6registerBeanPostProcessors()
  注册我们bean后置处理器:往容器中注册了我们的bean的后置处理器bean的后置处理器在什么时候进行调用?在bean的生命周期中parambeanFactoryparamapplicationContextpublicstaticvoidregisterBeanPostProcessors(ConfigurableListableBeanFactorybeanFactory,AbstractApplicationContextapplicationContext){去容器中获取所有的BeanPostProcessor的bean名称String〔〕postProcessorNamesbeanFactory。getBeanNamesForType(BeanPostProcessor。class,true,false);beanFactory。getBeanPostProcessorCount()获取的是已经添加在beanFactory的beanPostProcessors集合中的postProcessorNames。lengthbeanFactory工厂中BeanPostProcessor个数1又注册了BeanPostProcessorChecker的后置处理器intbeanProcessorTargetCountbeanFactory。getBeanPostProcessorCount()1postProcessorNames。length;beanFactory。addBeanPostProcessor(newBeanPostProcessorChecker(beanFactory,beanProcessorTargetCount));按照BeanPostProcessor实现的优先级接口来分离我们的后置处理器保存实现了priorityOrdered接口的ListBeanPostProcessorpriorityOrderedPostProcessorsnewArrayList();容器内部的ListBeanPostProcessorinternalPostProcessorsnewArrayList();实现了我们ordered接口的ListStringorderedPostProcessorNamesnewArrayList();实现了我们任何优先级的ListStringnonOrderedPostProcessorNamesnewArrayList();循环我们的bean定义(BeanPostProcessor)for(StringppName:postProcessorNames){若实现了PriorityOrdered接口的if(beanFactory。isTypeMatch(ppName,PriorityOrdered。class)){显示的调用getBean流程创建bean的后置处理器BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);加入到集合中priorityOrderedPostProcessors。add(pp);判断是否实现了MergedBeanDefinitionPostProcessorif(ppinstanceofMergedBeanDefinitionPostProcessor){加入到集合中internalPostProcessors。add(pp);}}判断是否实现了Orderedelseif(beanFactory。isTypeMatch(ppName,Ordered。class)){orderedPostProcessorNames。add(ppName);}else{nonOrderedPostProcessorNames。add(ppName);}}把实现了priorityOrdered注册到容器中sortPostProcessors(priorityOrderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,priorityOrderedPostProcessors);处理实现Ordered的bean后置处理器ListBeanPostProcessororderedPostProcessorsnewArrayList();for(StringppName:orderedPostProcessorNames){显示调用getBean方法BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);加入到集合中orderedPostProcessors。add(pp);判断是否实现了MergedBeanDefinitionPostProcessorif(ppinstanceofMergedBeanDefinitionPostProcessor){加入到集合中internalPostProcessors。add(pp);}}排序并且注册我们实现了Order接口的后置处理器sortPostProcessors(orderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,orderedPostProcessors);实例化我们所有的非排序接口的ListBeanPostProcessornonOrderedPostProcessorsnewArrayList();for(StringppName:nonOrderedPostProcessorNames){显示调用BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);nonOrderedPostProcessors。add(pp);判断是否实现了MergedBeanDefinitionPostProcessorif(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors。add(pp);}}注册我们普通的没有实现任何排序接口的registerBeanPostProcessors(beanFactory,nonOrderedPostProcessors);注册MergedBeanDefinitionPostProcessor类型的后置处理器sortPostProcessors(internalPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,internalPostProcessors);注册ApplicationListenerDetector应用监听器探测器的后置处理器beanFactory。addBeanPostProcessor(newApplicationListenerDetector(applicationContext));}3。7initMessageSource()
  初始化国际化资源处理器:InitializetheMessageSource。Useparentsifnonedefinedinthiscontext。protectedvoidinitMessageSource(){ConfigurableListableBeanFactorybeanFactorygetBeanFactory();if(beanFactory。containsLocalBean(MESSAGESOURCEBEANNAME)){this。messageSourcebeanFactory。getBean(MESSAGESOURCEBEANNAME,MessageSource。class);MakeMessageSourceawareofparentMessageSource。if(this。parent!nullthis。messageSourceinstanceofHierarchicalMessageSource){HierarchicalMessageSourcehms(HierarchicalMessageSource)this。messageSource;if(hms。getParentMessageSource()null){OnlysetparentcontextasparentMessageSourceifnoparentMessageSourceregisteredalready。hms。setParentMessageSource(getInternalParentMessageSource());}}if(logger。isDebugEnabled()){logger。debug(UsingMessageSource〔this。messageSource〕);}}else{UseemptyMessageSourcetobeabletoacceptgetMessagecalls。DelegatingMessageSourcedmsnewDelegatingMessageSource();dms。setParentMessageSource(getInternalParentMessageSource());this。messageSourcedms;beanFactory。registerSingleton(MESSAGESOURCEBEANNAME,this。messageSource);if(logger。isDebugEnabled()){logger。debug(UnabletolocateMessageSourcewithnameMESSAGESOURCEBEANNAME:usingdefault〔this。messageSource〕);}}}3。8initApplicationEventMulticaster()
  初始化事件多播器:从bean工厂中获取或者直接显示的new一个事件多播器赋值给applicatoinContext对象的applicationEventMulticaster属性事件多播器采用典型的设计模式就是观察者模式多播器作为的是一个被观察者seeorg。springframework。context。event。SimpleApplicationEventMulticasterprotectedvoidinitApplicationEventMulticaster(){获取我们的bean工厂对象ConfigurableListableBeanFactorybeanFactorygetBeanFactory();判断容器中是否包含了applicationEventMulticaster事件多播器组件if(beanFactory。containsLocalBean(APPLICATIONEVENTMULTICASTERBEANNAME)){直接显示的调用我们的getBean获取出来赋值给我们的applicationContext对象this。applicationEventMulticasterbeanFactory。getBean(APPLICATIONEVENTMULTICASTERBEANNAME,ApplicationEventMulticaster。class);if(logger。isDebugEnabled()){logger。debug(UsingApplicationEventMulticaster〔this。applicationEventMulticaster〕);}}容器中没有的话else{直接new一个this。applicationEventMulticasternewSimpleApplicationEventMulticaster(beanFactory);并且注入到容器中beanFactory。registerSingleton(APPLICATIONEVENTMULTICASTERBEANNAME,this。applicationEventMulticaster);if(logger。isDebugEnabled()){logger。debug(UnabletolocateApplicationEventMulticasterwithnameAPPLICATIONEVENTMULTICASTERBEANNAME:usingdefault〔this。applicationEventMulticaster〕);}}}3。9onRefresh()
  这个方法很重要,同样也是留个子类实现,其中SpringBoot就是从这个方法进行tomcat的启动。3。10registerListeners()
  把我们的事件监听器注册到事件多播器上:protectedvoidregisterListeners(){获取容器中所有的监听器对象for(ApplicationListenerlt;?listener:getApplicationListeners()){把监听器挨个的注册到我们的事件多播器上去getApplicationEventMulticaster()。addApplicationListener(listener);}获取bean定义中的监听器对象String〔〕listenerBeanNamesgetBeanNamesForType(ApplicationListener。class,true,false);把监听器的名称注册到我们的事件多播器上for(StringlistenerBeanName:listenerBeanNames){getApplicationEventMulticaster()。addApplicationListenerBean(listenerBeanName);}在这里获取我们的早期事件SetearlyEventsToProcessthis。earlyApplicationEvents;this。earlyApplicationEventsnull;if(earlyEventsToProcess!null){通过多播器进行播发早期事件for(ApplicationEventearlyEvent:earlyEventsToProcess){getApplicationEventMulticaster()。multicastEvent(earlyEvent);}}}
  如何发布事件,通过事件多播器方法:multicastEvent(),进入方法。OverridepublicvoidmulticastEvent(ApplicationEventevent){multicastEvent(event,resolveDefaultEventType(event));}OverridepublicvoidmulticastEvent(finalApplicationEventevent,NullableResolvableTypeeventType){ResolvableTypetype(eventType!null?eventType:resolveDefaultEventType(event));从事件多播器中获取出所有的监听器for(finalApplicationListenerlt;?listener:getApplicationListeners(event,type)){判断多播器中是否支持异步多播的ExecutorexecutorgetTaskExecutor();if(executor!null){异步播发事件executor。execute(()invokeListener(listener,event));}else{同步播发invokeListener(listener,event);}}}Invokethegivenlistenerwiththegivenevent。paramlistenertheApplicationListenertoinvokeparameventthecurrenteventtopropagatesince4。1protectedvoidinvokeListener(ApplicationListenerlt;?listener,ApplicationEventevent){ErrorHandlererrorHandlergetErrorHandler();if(errorHandler!null){try{doInvokeListener(listener,event);}catch(Throwableerr){errorHandler。handleError(err);}}else{doInvokeListener(listener,event);}}
  doInvokeListener()方法,Spring有一个特点,涉及到以do开头的方法都是真正干活的。SuppressWarnings({rawtypes,unchecked})privatevoiddoInvokeListener(ApplicationListenerlistener,ApplicationEventevent){try{listener。onApplicationEvent(event);}catch(ClassCastExceptionex){Stringmsgex。getMessage();if(msgnullmatchesClassCastMessage(msg,event。getClass())){Possiblyalambdadefinedlistenerwhichwecouldnotresolvethegenericeventtypeforletssuppresstheexceptionandjustlogadebugmessage。LogloggerLogFactory。getLog(getClass());if(logger。isTraceEnabled()){logger。trace(Nonmatchingeventtypeforlistener:listener,ex);}}else{throwex;}}}3。11finishBeanFactoryInitialization()
  实例化所有的非懒加载的单实例bean,我们前几篇源码,其实都是讲的里面的方法,最重要的就是getBean()。
  这个方法必须掌握,可以查看我的前几篇源码系列文章。3。12finishRefresh()
  最后刷新容器发布刷新事件(Springcloudeureka也是从这里启动的)。protectedvoidfinishRefresh(){初始化生命周期处理器initLifecycleProcessor();调用生命周期处理器的onRefresh方法getLifecycleProcessor()。onRefresh();发布ContextRefreshedEvent事件publishEvent(newContextRefreshedEvent(this));ParticipateinLiveBeansViewMBean,ifactive。LiveBeansView。registerApplicationContext(this);}
  (1)初始化生命周期处理器:initLifecycleProcessor()方法。protectedvoidinitLifecycleProcessor(){获取beanFactory工厂ConfigurableListableBeanFactorybeanFactorygetBeanFactory();判断容器中是否有lifecycleProcessor,有就直接从容器中拿if(beanFactory。containsLocalBean(LIFECYCLEPROCESSORBEANNAME)){this。lifecycleProcessorbeanFactory。getBean(LIFECYCLEPROCESSORBEANNAME,LifecycleProcessor。class);if(logger。isDebugEnabled()){logger。debug(UsingLifecycleProcessor〔this。lifecycleProcessor〕);}}没有创建一个DefaultLifecycleProcessor,然后注册到容器中else{DefaultLifecycleProcessordefaultProcessornewDefaultLifecycleProcessor();defaultProcessor。setBeanFactory(beanFactory);this。lifecycleProcessordefaultProcessor;beanFactory。registerSingleton(LIFECYCLEPROCESSORBEANNAME,this。lifecycleProcessor);if(logger。isDebugEnabled()){logger。debug(UnabletolocateLifecycleProcessorwithnameLIFECYCLEPROCESSORBEANNAME:usingdefault〔this。lifecycleProcessor〕);}}}
  (2)调用生命周期处理器的getLifecycleProcessor()。onRefresh()方法。OverridepublicvoidonRefresh(){startBeans(true);this。runningtrue;}
  startBeans(true)方法,主要的功能是找到Spring容器的Lifecycle类型的Bean,然后调用start()去启动。privatevoidstartBeans(booleanautoStartupOnly){MapString,LifecyclelifecycleBeansgetLifecycleBeans();MapInteger,LifecycleGroupphasesnewHashMapInteger,LifecycleGroup();for(Map。EntryString,?extendsLifecycleentry:lifecycleBeans。entrySet()){Lifecyclebeanentry。getValue();if(!autoStartupOnly(beaninstanceofSmartLifecycle((SmartLifecycle)bean)。isAutoStartup())){intphasegetPhase(bean);LifecycleGroupgroupphases。get(phase);if(groupnull){groupnewLifecycleGroup(phase,this。timeoutPerShutdownPhase,lifecycleBeans,autoStartupOnly);phases。put(phase,group);}group。add(entry。getKey(),bean);}}if(!phases。isEmpty()){ListIntegerkeysnewArrayListInteger(phases。keySet());Collections。sort(keys);for(Integerkey:keys){phases。get(key)。start();}}}
  phases。get(key)。start()方法。publicvoidstart(){if(this。members。isEmpty()){return;}if(logger。isDebugEnabled()){logger。debug(Startingbeansinphasethis。phase);}Collections。sort(this。members);for(LifecycleGroupMembermember:this。members){doStart(this。lifecycleBeans,member。name,this。autoStartupOnly);}}privatevoiddoStart(MapString,?extendsLifecyclelifecycleBeans,StringbeanName,booleanautoStartupOnly){LifecyclebeanlifecycleBeans。remove(beanName);if(bean!nullbean!this){String〔〕dependenciesForBeangetBeanFactory()。getDependenciesForBean(beanName);for(Stringdependency:dependenciesForBean){doStart(lifecycleBeans,dependency,autoStartupOnly);}bean不在运行中并且(autoStartupOnlyfalse或者不是SmartLifecycle类型或者isAutoStartup()true)if(!bean。isRunning()(!autoStartupOnly!(beaninstanceofSmartLifecycle)((SmartLifecycle)bean)。isAutoStartup())){if(logger。isDebugEnabled()){logger。debug(StartingbeanbeanNameoftype〔bean。getClass()。getName()〕);}try{调用生命周期LifecycleBean的start()方法bean。start();}catch(Throwableex){thrownewApplicationContextException(FailedtostartbeanbeanName,ex);}if(logger。isDebugEnabled()){logger。debug(SuccessfullystartedbeanbeanName);}}}}
  (3)发布ContextRefreshedEvent事件:主要就是调用前面第八步创建的事件多播器的发布事件方法。protectedvoidpublishEvent(Objectevent,ResolvableTypeeventType){Assert。notNull(event,Eventmustnotbenull);if(logger。isTraceEnabled()){logger。trace(PublishingeventingetDisplayName():event);}DecorateeventasanApplicationEventifnecessaryApplicationEventapplicationEvent;if(eventinstanceofApplicationEvent){applicationEvent(ApplicationEvent)event;}else{applicationEventnewPayloadApplicationEventObject(this,event);if(eventTypenull){eventType((PayloadApplicationEvent)applicationEvent)。getResolvableType();}}Multicastrightnowifpossibleorlazilyoncethemulticasterisinitializedif(this。earlyApplicationEvents!null){this。earlyApplicationEvents。add(applicationEvent);}else{getApplicationEventMulticaster()。multicastEvent(applicationEvent,eventType);}Publisheventviaparentcontextaswell。。。if(this。parent!null){if(this。parentinstanceofAbstractApplicationContext){((AbstractApplicationContext)this。parent)。publishEvent(event,eventType);}else{this。parent。publishEvent(event);}}}4。总结
  总结一下本文内容:讲述了IOC的基础知识,并通过婚介所的示例,讲解容器的创建过程;介绍容器创建的4个相关对象,以及refresh()的主流程;给出refresh()的12个主流程的核心源码,并附上详细注释。
  大家主要掌握IOC容器创建的思想和过程,以及refresh()的12个主流程即可,至于里面每一步流程,如果深究下去,其实内容非常多,建议后续如果需要,再深入学习。

江南人参!癌症患者调理的一大名将笔者留意发现,恰逢十月金秋,是很多应季蔬果、海鲜上市的季节,可对于肿瘤患者而言,日常饮食还是需要管住嘴,要悠着吃、选着吃。那这位既可作为水果,又可作为蔬菜,且被誉为江南人……武当山古建筑群武当山古建筑群的宫殿和庙宇体现了中国元、明、清建筑和艺术成就。古建筑群坐落在沟壑纵横、风景如画的湖北省武当山麓,在明代期间(1417世纪)逐渐形成规模,其中的道教建筑可以追溯到……跟着总书记看中国华溪村的小康生活视频加载中。。。大国之大,也有大国之重。千头万绪的事,说到底是千家万户的事。曾经的重庆市石柱土家族自治县中益乡华溪村,山高坡陡、土地贫瘠,是集中连片特困地区武陵山片……勇士揭幕战不敌湖人取得开门黑?珍妮如是分析,对决究竟走向如何NBA全新赛季已然在归来路上,将在几日之后如约开启,十月中旬清爽天气一派秋光景色,遍野金黄菊香飘荡,大洋彼岸再次上演关于总冠军奥布莱恩杯的故事。北京时间10月19日上午1……梦幻西游手游低配队如何上王者?选对70装备,加分冲段犹如喝水在《梦幻西游》手游中,随着时间来到全新版本,各种小特技的要求是越来越多,不仅要有物理层面上的放下屠刀和野兽之力,法系层面上也要有全新特技立地成佛和凤舞九天。毕竟一个特技就……放养被爆冷,刘国梁出手,肖战或接手王楚钦,王曼昱或迎42岁名王楚钦在8进4倒在了韩国球员的手上,这是球迷没有意料到的,特别是这场比赛,王楚钦并没有放水,王楚钦也几乎是拼尽了全力,结果还是输球。输掉这场比赛,有王楚钦自身的原因,也有……清水洗头治秃顶?想要防治秃顶,这些才是重点虽说十个光头九个富,但事实上秃顶非常影响一个人的外貌,每个秃顶的人都希望自己能满头黑发。近日,一名男子说自己坚持半年清水洗头,从秃顶变满头黑发,从而引起了很多人的关注。……典藏版价格逆天?碧蓝航线埃吉尔出手办了埃吉尔是游戏《碧蓝航线》中的角色,而最近ACTOYS也是带来了一款埃吉尔的手办,本品分为了轻装以及典藏两个版本,我们一起来看看吧!轻装版这款埃吉尔手办采用了17的比……三部门集体约谈多晶硅骨干企业,暴涨的硅料距离降价还有多远创出十年新高的光伏多晶硅价格引发相关主管部门的密切关注。工信部网站10月9日下午发布消息,根据工信部、市场监管总局、国家能源局(下称三部门)联合印发的《关于促进光伏产业链供应链……苹果秋季发布会就是明天,改变世界的奇迹还会再次发生吗?苹果2022年发布会即将开始改变世界的奇迹还会再次诞生吗?锁定日报直播间9月8日一起见证苹果新品的诞生苹果秋季发布会,一起见证iPhone14问世!……JDG让二追三的秘诀暴露,教练在后台立大功,其他战队应该学学现在电竞行业的热度是非常高的,最近相信大家也看到不少这方面的内容,季后赛这么多太精彩了,小编看完之后也是热血沸腾,果然最终和小编的预测一样,就今年TES和JDG的状态,不管谁输……降价最快的几款手机,性价比高,续航强,价格便宜的手机闪闪发光的他大部分人在购买手机的时候,都想花更少的钱买到配置强的手机,但如今大家对手机的性能和续航要求同样很高,所以,有没有人同时兼顾这两点的手机呢,有没有兼顾性能、价格、续航……
孙杨上诉驳回后首次回应退役从未放弃过训练,也没有打算退役虽然在去年的东京奥运会上,中国游泳队取得了相当不错的成绩,但是很多国人还是对于昔日的长距离王者孙杨的缺席感到无比遗憾,网友纷纷表示,如果孙杨能够参赛,那么中国游泳队必将再添多枚……盘点巨星代言品牌,詹皇库里大品牌,阿迪眼光最独特耐克、阿迪、乔丹这样的运动品牌和NBA球星之间是互相成就的关系。品牌签约能扩大球星自身影响力,超人气球星也能给品牌创造宣传和镀金价值,他们互惠互利,共同发展。球星品……这是谁家的新娘?皇马球员动态汇总0625恭喜卡瓦哈尔夫妇,卡2这是属于晚婚晚育了吧?先上卡嫂美图!婚礼发型师发的新娘造型婚礼现场和晚宴的官图估计要过两天才出来,敬请期待!前来祝贺的队友们库尔图瓦和米……又伤了!火箭新秀遭伤病夏联报销,塞拉斯无奈,斯通会放弃他吗北京时间7月10日,NBA拉斯维加斯夏季联赛进行到了第三个比赛日,今天火箭队将会面对到的是实力强劲的雷霆队。在上一场比赛中他们已经输给了魔术队,所以现在对于火箭来说非常危险,再……抢人大战开始,2018届的果子熟了,今年夏天联盟会多几位亿元毋庸置疑,2018年的选秀是近几年来成色最高的一届,并且在去年的时候就已经有东契奇、杨、布里奇斯、亚历山大等球员达成了续约,不过对比起提前续约的球员,今年合同到期的球员才是其他……那些难免落俗的烂漫文案,非常值得一看1。别回头看,身后万千灯盏,都不是你的归处2。从今天开始我就不打算喜欢你了,一直都挺累的挺失望的,真的,喜欢你这么久你都没有回应,我可是被我爸妈从小宠到大的,凭什么要在你……输广厦负山西,卫冕冠军这是要躺平的节奏吗输广厦,负山西,卫冕冠军这是要躺平的节奏吗联赛15轮,广东遇上了山西。没想到,大比分输掉了比赛。其实,这胜败本是常事,可输给了联赛实力稍弱的山西,而且是99:125,26……星动力国星宇航星时代10卫星(广东恒健号)顺利完成在轨测试并近日,国星宇航组织召开了星时代10卫星(广东恒健号)在轨测试总结评审会。目前,该卫星在轨运行状态良好,星时代10卫星在轨测试圆满完成,具备转入业务化运行的条件。今年7月3……国产手机格局变动!国内看vivo,国外看小米这两年随着华为手机的退隐,国产手机都争着来分一杯羹,几大手机厂商你来我往地过招,结果大头还是被苹果默默地抢手了,国产手机也就瓜分了剩下的低端市场和少量的高端份额,因为苹果没有低……真香红米沦为千元机,骁龙870三星E4屏,还有OIS光学防抖手机市场竞争激烈,特别是国内的这种环境,没有性价比就是死路一条,很多厂商已经证明了这点,例如倒闭的锤子科技,苟延残喘的魅族等等,连不将就的一加如今也来到OPPO旗下,成为高性价……MIUIGo曝光小内存也能有丝滑的体验,可用内存翻倍目前的手机软件占用和内存越来越大,很多仅隔一年就发现使用部分软件就开始卡顿变慢这实则并不是手机硬件的问题,而是软件体积变大导致了手机硬件性能达不到要求。这也是国内的……年轻时惊为天人,老了成胖大婶,这7位身材走样的女星好可惜最近向佐被曝出轨,向太陈岚又因替儿子发声成为大家讨论的焦点。这个女子在大部分网友眼里是霸气强势的,甚至很多人说她光看面相就不好惹。但很多人不知道的是,她年轻的时候也是一个……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网