专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

源码深度解析之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个主流程即可,至于里面每一步流程,如果深究下去,其实内容非常多,建议后续如果需要,再深入学习。

讣告越来越多!院士教授药企高管殡葬大小王股价躁动,一只暴涨81自国内疫情放开后,资本市场讨论较多的两只股票,一个是A股的福成股份,一个是港股的福寿园。福成股份主业是肉牛养殖屠宰及食品加工,主要产品除了牛羊肉牛奶等食品,还包括墓地福寿园则是中国天眼查发布2022中国数字经济主题报告近年来,互联网大数据云计算人工智能区块链等技术加速创新,日益融入经济社会发展各领域全过程。中国信息通信研究院调研显示,2021年,全球47个主要国家数字经济增加值规模达到38。1万国家统计局最终核实2021年GDP比初步核算数增加5567亿元光明网讯(记者赵艳艳)按照我国国内生产总值(GDP)核算和数据发布制度规定,年度GDP核算包括初步核算和最终核实两个步骤。近日,根据国家统计局统计年报财政部财政决算和有关部门年度财抓创新拓市场浙江民营经济不断发展壮大央视网消息(新闻联播)浙江为民营企业解难题办实事,构建亲清政商关系,扶持民营企业抓创新拓市场,民营经济不断发展壮大。前不久,位于杭州的传化集团高端智能制造工厂开工建设。今年,传化已稳楼市,财税政策能做些什么?经济观察网记者杜涛12月召开的中央经济工作会议提出,要确保房地产市场平稳发展,扎实做好保交楼保民生保稳定各项工作,满足行业合理融资需求,推动行业重组并购,有效防范化解优质头部房企风QQ音乐用户年度听歌报告来了!年度红心单曲孤勇者南都讯南都记者黄璐年终岁末各大盘点即将如约而至。南都记者从QQ音乐获悉,2022年度听歌报告近日正式上线,QQ音乐首页登录即可查看自己的年度音乐记忆。在这一年中一路同行的歌手是谁?搭建灵活就业云平台提供均等化常住地无差别服务央视网消息面对求职当中存在的各种困难,有关部门在打通就业堵点上下功夫,取消就业报到证补办改派手续。对离校未就业毕业生做好不断线服务,着力消除就业障碍简化就业手续提升就业能力。在湖北凯迪拉克锐歌四驱版上市,通用奥特能平台与你相约长沙车展12月21日,凯迪拉克LYRIQ锐歌四驱高性能版正式上市,与普通版车型相比,四驱版车型提速更为迅猛,百公里加速仅为4。9秒。据悉,新车将于12月26日起开始陆续交付。也就是说,在2(星空有约)2022年最后一场赏心悦目的星月童话29日上演新华社天津12月27日电(记者周润健)天文科普专家介绍,12月29日晚天宇将上演木星合月,这是2022年最后一场行星合月。届时只要天气晴好,我国公众可在南方天空欣赏到明亮木星与一轮中国2030年载人登月计划已定!美国不让去其登月地点,要同意吗!美国在2020年底发布了在太空中保护人类遗产的一小步法,其将阿波罗登月留下的遗址和遗物划分为文物,而且还规定其他国家在登月的时候,不允许去它当年的登月遗址。好家伙,美国这是在月球圈中国成功发射高分十一号04星中新网北京12月27日电(马帅莎喻鹏王茄欢郝明鑫)北京时间12月27日15时37分,中国在太原卫星发射中心使用长征四号乙运载火箭,成功将高分十一号04星发射升空,卫星顺利进入预定轨
星期特刊丨从英雄联盟走进战斗军营从英雄联盟走进战斗军营武警广东总队茂名支队上等兵潘显华的跨界之旅当新生事物夹杂着未知的风险涌入军营,让我们以发展的眼光认真研究应对之策,而非图省心省事一堵了之。题记潘显华是个南方小中国跨度最大的桥,跨江1700米不设桥墩,10万吨桥体怎么浮起来?在我国长江之上,有一座名叫杨泗港长江大桥的跨江工程,与传统带有桥墩的混凝土大桥不同,它的总长度虽然达到了1700米,但却没有使用一个桥墩,而是由一根又一根的钢缆将桥面拉到了空中。那交会对接成功!航天员入驻太空家园要过三个舱开四道门央视直播截图据中国载人航天工程办公室消息,北京时间2022年6月5日17时42分,神舟十四号载人飞船与空间站组合体成功完成自主快速交会对接。接下来,航天员想要入驻太空家园,还需过三中国首位飞天女航天员刘洋再登太空据中国载人航天工程办公室消息,经空间站阶段飞行任务总指挥部研究决定,陈冬刘洋蔡旭哲3名航天员将执行神舟十四号载人飞行任务,由陈冬担任指令长。(神州十四号飞行乘组)随着执行神舟十四号美媒中国被美制隐身战机半包围,F随着,美军在印太地区加紧军事力量部署,试图在印太地区打造出呈现出半包围的军事圈,沿着军事圈部署第五代隐身战斗机,再加上美海军航空母舰搭载F35C舰载战斗机,两栖攻击舰搭载F35B战彻底告别亚洲杯,李璇坐实中国足协谈崩亚足联,五年内不会举办随着中超联赛的开赛,中国足球重新拾起了关注度。在国内足球保持了火种以后,让大家重新对于足球开始关心起来。而且从中超开赛以后的对抗程度,从比赛里球员展现出来的一些面貌气质,我们能够解神舟1号到14号历次发射瞬间回眸不知不觉一晃二十多年过去了,从1999年发射的神舟1号,到2003年的载人神5,到今天的神舟14号,20多年的时间里,我们中国航天实现了一个又一个突破,实现了一个又一个超越,我们突声生不息第7期李克勤演绎20年前粤语中国风,文学性极强今天我们继续用文学的方式打开声生不息第7期炎明熹心淡等闲变却故人心,却道故人心易变。心淡是容祖儿的代表作,也是新世纪粤语情歌经典作品,歌中将恋爱时的卑微描写的形象而深刻。令人意想不神回复我该怎么劝阻这种不文明行为?网友劝你不要多管闲事万丈高楼平地起,小丑竟是我自己到底好看不好看,是谁说了算牛牛往后余生,全靠老弟的提携也是大品牌LV的,你老婆肯定会喜欢的道路千万条,安全第一条如果是你话,你喜欢哪一种国人要知道旗帜男子去嫖娼,先支付了嫖资后有事转给自己哥们,哥们最后却被刑拘色字头上一把刀,英雄难过美人关,今天这个案例就是由色字引起的。案情再现张军(化名),有一日想放松放松,就在网上联系了一位洗浴中心的技师李丽(化名)。二人约定好晚上6点在某酒店进行交安徽农村打工男子通过手术,摇身一变成女郎,究竟是为了什么?我在头条搞创作现在这大千世界,无奇不有。一个完整无缺的健康正常的阳刚活泼的青年男子,真不知道是什么动力,什么魔力让这位男人,非要将自己的男儿身,摇身一变,成为一个美女。当然,这里并
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网