Spring IoC学习之ApplicationContext中refresh过程详解
refresh()
该方法是SpringBean加载的核心,它是ClassPathXmlApplicationContext的父类AbstractApplicationContext的一个方法,顾名思义,用于刷新整个Spring上下文信息,定义了整个Spring上下文加载的流程。
publicvoidrefresh()throwsBeansException,IllegalStateException{ synchronized(this.startupShutdownMonitor){ //准备刷新上下文环境 this.prepareRefresh(); //初始化BeanFactory,并进行XML文件读取 /* *ClassPathXMLApplicationContext包含着BeanFactory所提供的一切特征,在这一步骤中将会复用 *BeanFactory中的配置文件读取解析及其他功能,这一步之后,ClassPathXmlApplicationContext *实际上就已经包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基础操作了。 */ ConfigurableListableBeanFactorybeanFactory=this.obtainFreshBeanFactory(); //对beanFactory进行各种功能填充 this.prepareBeanFactory(beanFactory); try{ //子类覆盖方法做额外处理 this.postProcessBeanFactory(beanFactory); //激活各种beanFactory处理器 this.invokeBeanFactoryPostProcessors(beanFactory); //注册拦截Bean创建的Bean处理器,这里只是注册,真正的调用实在getBean时候 this.registerBeanPostProcessors(beanFactory); //为上下文初始化Message源,即不同语言的消息体,国际化处理 this.initMessageSource(); //初始化应用消息广播器,并放入“applicationEventMulticaster”bean中 this.initApplicationEventMulticaster(); //留给子类来初始化其它的Bean this.onRefresh(); //在所有注册的bean中查找Listenerbean,注册到消息广播器中 this.registerListeners(); //初始化剩下的单实例(非惰性的) this.finishBeanFactoryInitialization(beanFactory); //完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人 this.finishRefresh(); }catch(BeansExceptionvar9){ if(this.logger.isWarnEnabled()){ this.logger.warn("Exceptionencounteredduringcontextinitialization-cancellingrefreshattempt:"+var9); } this.destroyBeans(); this.cancelRefresh(var9); throwvar9; }finally{ this.resetCommonCaches(); } } }
每个子方法的功能之后一点一点再分析,首先refresh()方法有几点是值得我们学习的:
- 方法是加锁的,这么做的原因是避免多线程同时刷新Spring上下文;
- 尽管加锁可以看到是针对整个方法体的,但是没有在方法前加synchronized关键字,而使用了对象锁startUpShutdownMonitor,这样做有两个好处:
(1)refresh()方法和close()方法都使用了startUpShutdownMonitor对象锁加锁,这就保证了在调用refresh()方法的时候无法调用close()方法,反之依然,这样就避免了冲突。
(2)使用对象锁可以减小同步的范围,只对不能并发的代码块进行加锁,提高了整体代码运行的速率。 - 在refresh()方法中整合了很多个子方法,使得整个方法流程清晰易懂。这样一来,方便代码的可读性和可维护性。
3.1prepareRefresh方法
//设置启动时间,是否激活标识位,初始化属性源(propertysource)配置 protectedvoidprepareRefresh(){ this.startupDate=System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if(this.logger.isDebugEnabled()){ if(this.logger.isTraceEnabled()){ this.logger.trace("Refreshing"+this); }else{ this.logger.debug("Refreshing"+this.getDisplayName()); } } //在上下文环境中初始化任何占位符属性源。(空的方法,留给子类覆盖) this.initPropertySources(); //验证所有的必需的属性是否可解析,若无则不能解析并抛出异常 this.getEnvironment().validateRequiredProperties(); if(this.earlyApplicationListeners==null){ this.earlyApplicationListeners=newLinkedHashSet(this.applicationListeners); }else{ this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } this.earlyApplicationEvents=newLinkedHashSet(); }
prepareRefresh的内容如上,该方法主要进行环境的准备,包括Context的启动时间,活动状态,然后设置context中的配置数据源,使用默认的StandardEnvironment对象,该对象添加了System.env()属性和System.properties()属性。initPropertySources方法用于初始化context中environment的属性源。在AbstractApplicationContext中为空实现。其他子类的实现如下:
在子类GenericWebApplicationContext和AbstractRefreshableWebApplicationContext的实现大致一致,都是:
protectedvoidinitPropertySources(){ ConfigurableEnvironmentenv=this.getEnvironment(); if(envinstanceofConfigurableWebEnvironment){ ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext,this.servletConfig); } }
通过在getEnvironment方法中,重写createEnvironment方法。
protectedConfigurableEnvironmentcreateEnvironment(){ returnnewStandardServletEnvironment(); }
将AbstractApplicationContext类中默认的StandardEnvironment替换为StandardServletEnvironment,StandardServletEnvironment的关系图为:
因而会执行StandardServletEnvironment类的initPropertySources方法,为context添加ServletContext和ServletConfig对应的配置属性源。
publicvoidinitPropertySources(@NullableServletContextservletContext,@NullableServletConfigservletConfig){ WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(),servletContext,servletConfig); }
接着是分析this.getEnvironment().validateRequiredProperties()方法,在上述我们已经提到getEnvironment()返回的不再是默认的StandardEnvironment而是替换为了StandardServletEnvironment,在此基础上查找validateRequiredProperties()的实现方法,最终定位到了AbstractEnvironment类中:
publicvoidvalidateRequiredProperties()throwsMissingRequiredPropertiesException{ this.propertyResolver.validateRequiredProperties(); }
this.propertyResolver指的是PropertySourcesPropertyResolver对象,最终具体实现定位在AbstractPropertyResolver类中:
publicvoidvalidateRequiredProperties(){ MissingRequiredPropertiesExceptionex=newMissingRequiredPropertiesException(); Iteratorvar2=this.requiredProperties.iterator(); while(var2.hasNext()){ Stringkey=(String)var2.next(); if(this.getProperty(key)==null){ ex.addMissingRequiredProperty(key); } } if(!ex.getMissingRequiredProperties().isEmpty()){ throwex; } }
3.2obtainFreshBeanFactory
该方法的实现如下,通过refreshBeanFactory重置AbstractApplicationContext持有的BeanFactory,然后通过getBeanFactory获取该对象并返回。
protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){ this.refreshBeanFactory(); returnthis.getBeanFactory(); }
AbstractApplicationContext中refreshBeanFacoty方法和getBeanFactory方法都是抽象方法,具体实现在AbstractRefreshableApplicationContext中。
protectedfinalvoidrefreshBeanFactory()throwsBeansException{ if(this.hasBeanFactory()){ //销毁已经存在的单例bean this.destroyBeans(); //销毁已有的BeanFactory this.closeBeanFactory(); } try{ //创建一个新的beanFactory,类型为DefaultListableBeanFactory DefaultListableBeanFactorybeanFactory=this.createBeanFactory(); //设置序列化id,为实例对象内存中的十六进制标识 beanFactory.setSerializationId(this.getId()); //定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖以及设置 this.customizeBeanFactory(beanFactory); //加载BeanDefiniton this.loadBeanDefinitions(beanFactory); synchronized(this.beanFactoryMonitor){ this.beanFactory=beanFactory; } }catch(IOExceptionvar5){ thrownewApplicationContextException("I/Oerrorparsingbeandefinitionsourcefor"+this.getDisplayName(),var5); } }
loadBeanDefinitions在AbstractRefreshableApplicationContext中是个抽象方法,具体实现是在AbstractXmlApplicationContext中:
protectedvoidloadBeanDefinitions(DefaultListableBeanFactorybeanFactory)throwsBeansException,IOException{ //为当前工厂创建xml解析器 XmlBeanDefinitionReaderbeanDefinitionReader=newXmlBeanDefinitionReader(beanFactory); //配置当前环境 beanDefinitionReader.setEnvironment(this.getEnvironment()); //配置资源解析器 beanDefinitionReader.setResourceLoader(this); //配置schemas或者dtd的资源解析器,EntityResolver维护了url->schemalocation的路径 beanDefinitionReader.setEntityResolver(newResourceEntityResolver(this)); //子类提供自定义的reader的初始化方法 this.initBeanDefinitionReader(beanDefinitionReader); //加载bean定义 this.loadBeanDefinitions(beanDefinitionReader); }
在loadBeanDefinitions方法中传入了DefaultListableBeanFactory对象,并且初始化了XmlBeanDefinitionReader对象,接着就是初始化bean工厂的一些环境、类加载器等。继续进入到loadBeanDefinitions(beanDefinitionReader)方法体中,代码如下:
protectedvoidloadBeanDefinitions(XmlBeanDefinitionReaderreader)throwsBeansException,IOException{ Resource[]configResources=this.getConfigResources(); if(configResources!=null){ reader.loadBeanDefinitions(configResources); } String[]configLocations=this.getConfigLocations(); if(configLocations!=null){ reader.loadBeanDefinitions(configLocations); } }
这里的configResources和configLocations对应两种构造函数,其中configLocations是构造函数A使用的。关于loadBeanDefinitions方法涉及的内容比较多,我们挑一些重要的来看。以下是AbstractBeanDefinitionReader类中的loadBeanDefinitions方法。
上述方法主要做两件事:
- 调用资源加载器获取资源resourceLoader.getResource(location)。
- 真正执行加载功能的是子类XmlBeanDefinitionReader的loadBeanDefinitions方法。
其中getResources方法是在PathMatchingResourcePatternResolver类实现的。
publicResource[]getResources(StringlocationPattern)throwsIOException{ Assert.notNull(locationPattern,"Locationpatternmustnotbenull"); if(locationPattern.startsWith("classpath*:")){ returnthis.getPathMatcher().isPattern(locationPattern.substring("classpath*:".length()))?this.findPathMatchingResources(locationPattern):this.findAllClassPathResources(locationPattern.substring("classpath*:".length())); }else{ intprefixEnd=locationPattern.startsWith("war:")?locationPattern.indexOf("*/")+1:locationPattern.indexOf(58)+1; returnthis.getPathMatcher().isPattern(locationPattern.substring(prefixEnd))?this.findPathMatchingResources(locationPattern):newResource[]{this.getResourceLoader().getResource(locationPattern)}; } }
count=this.loadBeanDefinitions(resources);中的loadBeanDefinitions方法具体实现在XmlBeanDefinitionReader类中。
publicintloadBeanDefinitions(EncodedResourceencodedResource)throwsBeanDefinitionStoreException{ Assert.notNull(encodedResource,"EncodedResourcemustnotbenull"); if(this.logger.isTraceEnabled()){ this.logger.trace("LoadingXMLbeandefinitionsfrom"+encodedResource); } SetcurrentResources=(Set)this.resourcesCurrentlyBeingLoaded.get(); if(currentResources==null){ currentResources=newHashSet(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if(!((Set)currentResources).add(encodedResource)){ thrownewBeanDefinitionStoreException("Detectedcyclicloadingof"+encodedResource+"-checkyourimportdefinitions!"); }else{ intvar5; try{ //将资源文件转换为类型为InputStream的I/O流 InputStreaminputStream=encodedResource.getResource().getInputStream(); try{ //从InputStream中得到xML的解析源 InputSourceinputSource=newInputSource(inputStream); //编码如果不为null,则设置inputSource的编码 if(encodedResource.getEncoding()!=null){ inputSource.setEncoding(encodedResource.getEncoding()); } var5=this.doLoadBeanDefinitions(inputSource,encodedResource.getResource()); }finally{ inputStream.close(); } }catch(IOExceptionvar15){ thrownewBeanDefinitionStoreException("IOExceptionparsingXMLdocumentfrom"+encodedResource.getResource(),var15); }finally{ ((Set)currentResources).remove(encodedResource); if(((Set)currentResources).isEmpty()){ this.resourcesCurrentlyBeingLoaded.remove(); } } returnvar5; } }
getInputStream方法用来加载XML文件,具体实现在ClassPathResource类中,
publicInputStreamgetInputStream()throwsIOException{ InputStreamis; if(this.clazz!=null){ is=this.clazz.getResourceAsStream(this.path); }elseif(this.classLoader!=null){ is=this.classLoader.getResourceAsStream(this.path); }else{ is=ClassLoader.getSystemResourceAsStream(this.path); } if(is==null){ thrownewFileNotFoundException(this.getDescription()+"cannotbeopenedbecauseitdoesnotexist"); }else{ returnis; } }
doLoadBeanDefinitions用来注册bean。
protectedintdoLoadBeanDefinitions(InputSourceinputSource,Resourceresource)throwsBeanDefinitionStoreException{ try{ //转化为Document对象 Documentdoc=this.doLoadDocument(inputSource,resource); //启动对Bean定义解析的详细过程,会用到SpringBean的配置规则 intcount=this.registerBeanDefinitions(doc,resource); if(this.logger.isDebugEnabled()){ this.logger.debug("Loaded"+count+"beandefinitionsfrom"+resource); } returncount; }catch(BeanDefinitionStoreExceptionvar5){ throwvar5; ..... }
后续关联的代码在此就不做介绍,后期我们再学习。
因为在XmlBeanDefinitionReader中已经将之前初始化的DefaultListableBeanFactory注册进去了,所以XmlBeanDefinitionReader所读取的BeanDefinitionHolder都会注册到DefinitionListableBeanFactory中,也就是经过这个步骤,DefaultListableBeanFactory的变量beanFactory已经包含了所有解析好的配置。
至此通过加载XML文件,将xml文件解析为对应的BeanDefinition,完成了Bean定义的加载和注册。
3.3prepareBeanFactory
protectedvoidprepareBeanFactory(ConfigurableListableBeanFactorybeanFactory){ //设置beanFactory的classLoader为当前context的classloader beanFactory.setBeanClassLoader(this.getClassLoader()); //设置beanFactory的表达式语言处理器,Spring3增加了表达式语言的支持, //默认可以使用#{bean.xxx}的形式来调用相关属性值 beanFactory.setBeanExpressionResolver(newStandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //设置PropertyEditorRegistrar,通过PropertyEditor将xml解析出来的bean属性(字符串)和相应的java类型做转换 beanFactory.addPropertyEditorRegistrar(newResourceEditorRegistrar(this,this.getEnvironment())); /** 添加后置处理器ApplicationContextAwareProcessor,在Bean初始化后自动执行各Aware接口的set方法,包括ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware **/ beanFactory.addBeanPostProcessor(newApplicationContextAwareProcessor(this)); 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、ResourceLoader、ApplicationEventPublisher、ApplicationContext beanFactory.registerResolvableDependency(BeanFactory.class,beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class,this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class,this); beanFactory.registerResolvableDependency(ApplicationContext.class,this); //在bean实例化后,添加ApplicationListenerDetector,可以理解成:注册事件监听器 beanFactory.addBeanPostProcessor(newApplicationListenerDetector(this)); //如果存在loadTimeWeaver这个Bean,则增加对应的后置处理器 if(beanFactory.containsBean("loadTimeWeaver")){ beanFactory.addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //添加默认的系统环境bean if(!beanFactory.containsLocalBean("environment")){ beanFactory.registerSingleton("environment",this.getEnvironment()); } if(!beanFactory.containsLocalBean("systemProperties")){ beanFactory.registerSingleton("systemProperties",this.getEnvironment().getSystemProperties()); } if(!beanFactory.containsLocalBean("systemEnvironment")){ beanFactory.registerSingleton("systemEnvironment",this.getEnvironment().getSystemEnvironment()); } }
其中反复出现了addBeanPostProcessor方法,该方法具体实现在AbstractBeanFactory类中。
publicvoidaddBeanPostProcessor(BeanPostProcessorbeanPostProcessor){ Assert.notNull(beanPostProcessor,"BeanPostProcessormustnotbenull"); this.beanPostProcessors.remove(beanPostProcessor); if(beanPostProcessorinstanceofInstantiationAwareBeanPostProcessor){ this.hasInstantiationAwareBeanPostProcessors=true; } if(beanPostProcessorinstanceofDestructionAwareBeanPostProcessor){ this.hasDestructionAwareBeanPostProcessors=true; } this.beanPostProcessors.add(beanPostProcessor); }
详细分析下代码发现上面函数主要是在以下方法进行了扩展:
- 对SPEL语言的支持
- 增加对属性编辑器的支持
- 增加对一些内置类的支持,如EnvironmentAware、MessageSourceAware的注入
- 设置了依赖功能可忽略的接口
- 注册一些固定依赖的属性
- 如果存在loadTimeWeaver这个Bean,则增加对应的后置处理器
- 将相关环境变量及属性以单例模式注册
3.4postProcessBeanFactory
所有Bean的定义已经加载完成,但是没有实例化,这一步可以修改bean定义或者增加自定义的bean。该方法主要是承接上文中的prepareBeanFactory方法,增加一些后置处理器。具体实现在AbstractRefreshableWebApplicationContext类中。
protectedvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory){ //增加ServletContextAwareProcessor后置处理器 //用于处理ServletContextAware接口和ServletConfigAware接口中相关对象的自动注入 beanFactory.addBeanPostProcessor(newServletContextAwareProcessor(this.servletContext,this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); //注册web环境,包括request、session、golableSession、application WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,this.servletContext); //注册servletContext、contextParamters、contextAttributes、servletConfig单例bean WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,this.servletContext,this.servletConfig); }
3.5invokeBeanFactoryPostProcessors
protectedvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory){ PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,this.getBeanFactoryPostProcessors()); if(beanFactory.getTempClassLoader()==null&&beanFactory.containsBean("loadTimeWeaver")){ beanFactory.addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
在执行invokeBeanFactoryPostProcessors方法前查看beanFactory,对比执行后发现此处有所不同。
在Spring容器中找出实现了BeanFactoryPostProcessor接口的Bean并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行。
通过调试发现,ClassPathXmlApplicationContext类中的beanFactoryPostProcessors属性为空,所以执行invokeBeanFactoryPostProcessors方法时也是如此。
那么我们执行该方法有什么用呢?那么还有什么地方可能存在实现了BeanFactoryPostProcessor接口的Bean,带着疑问,我们去查看PostProcessorRegistrationDelegate中的invokeBeanFactoryPostProcessors方法。
publicstaticvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory,ListbeanFactoryPostProcessors){ Set processedBeans=newHashSet(); ArrayListregularPostProcessors; ArrayListregistryProcessors; intvar9; .... }
这一段代码特别长,一开始看起来肯定觉得很难,不知道从哪入手,这里我介绍一下我的学习方法,对测试代码进行debug调试,进入该方法后一步一步往下执行,遇到外部引用的方法记下来,待会调试完毕找到该方法,然后再打断点进行调试。反复来几遍,大概就能理解这个方法做了什么事情。
首先该方法的参数beanFactory实际类型为DefaultListableBeanFactory,beanFactoryPostProcessors参数内容为空。调试过程中发现比较重要的方法是getBeanNamesForType方法,该方法有三个参数值,具体实现在DefaultListableBeanFactory类中。
publicString[]getBeanNamesForType(@NullableClass>type,booleanincludeNonSingletons,booleanallowEagerInit){ if(this.isConfigurationFrozen()&&type!=null&&allowEagerInit){ Map,String[]>cache=includeNonSingletons?this.allBeanNamesByType:this.singletonBeanNamesByType; String[]resolvedBeanNames=(String[])cache.get(type); if(resolvedBeanNames!=null){ returnresolvedBeanNames; }else{ resolvedBeanNames=this.doGetBeanNamesForType(ResolvableType.forRawClass(type),includeNonSingletons,true); if(ClassUtils.isCacheSafe(type,this.getBeanClassLoader())){ cache.put(type,resolvedBeanNames); } returnresolvedBeanNames; } }else{ returnthis.doGetBeanNamesForType(ResolvableType.forRawClass(type),includeNonSingletons,allowEagerInit); } }
invokeBeanFactoryPostProcessors方法代码在调用getBeanNamesForType方法时根据第一个参数类型的不同分为两类:BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。其中BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor。执行的时候,先找出所有的BeanDefinitionRegistryPostProcessor执行再找出所有BeanFactoryPostProcessor执行。因为BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以执行后者时会过滤掉前者的内容。
在调试中发现只有当参数为BeanFactoryPostProcessor.class时,才会获取到有效的内容。getBeanNamesForType方法中的关键部分是doGetBeanNamesForType方法,该方法主要是将XML文件中定义的实现了BeanFactoryPostProcessor的bean的id取出来,以及将XML文件中定义的bean加载到beanFactory中。
等待getBeanNamesForType返回这些内容后,接着就会实例化并初始化实现BeanFactoryPostProcessor接口的类并执行。这里比较关键的代码是invokeBeanFactoryPostProcessors和PropertyResourceConfigurer类中的postProcessBeanFactory方法。
privatestaticvoidinvokeBeanFactoryPostProcessors(CollectionpostProcessors,ConfigurableListableBeanFactorybeanFactory){ Iteratorvar2=postProcessors.iterator(); while(var2.hasNext()){ BeanFactoryPostProcessorpostProcessor=(BeanFactoryPostProcessor)var2.next(); postProcessor.postProcessBeanFactory(beanFactory); } } publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{ try{ PropertiesmergedProps=this.mergeProperties(); this.convertProperties(mergedProps); this.processProperties(beanFactory,mergedProps); }catch(IOExceptionvar3){ thrownewBeanInitializationException("Couldnotloadproperties",var3); } }
当PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法执行完毕后,查看beanFactory的状态。
3.6registerBeanPostProcessors
从Spring容器中找出的BeanPostProcessor接口的Bean,并添加到BeanFactory内部维护的List属性中,以便后续Bean被实例化的时候调用这个BeanPostProcessor进行回调处理。该方法委托给了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。
同invokeBeanFactoryPostProcessors类似,先从容器中获取所有类型为BeanPostProcessor.class的Bean的name数组,然后通过BeanPostProcessorpp=beanFactory.getBean(ppName,BeanPostProcessor.class);获取Bean的实例,最后通过registerBeanPostProcessors(beanFactory,orderedPostProcessors);将获取到的BeanPostProcessor实例添加到容器的属性中。在实际过程中会根据AbstractBeanFactory类中的isTypeMatch方法对bean实例进行筛选,具体顺序为:
- 将实现PriorityOrdered接口的BeanPostProcessor列表添加到beanFactory中
- 将实现Ordered接口的BeanPostProcessor列表添加到beanFactory中
- 将剩余的BeanPostProcessor列表添加到beanFactory中
- 将实现MergedBeanDefinitionPostProcessor接口的BeanPostProcessor列表添加到beanFactory中
另外在PostProcessorRegistrationDelegate类中有个内部类BeanPostProcessorChecker,它实现了BeanPostProcessor接口,所以最后会有一个BeanPostProcessorChecker类添加到beanFactory中。
最终该方法用来实例化并初始化实现BeanPostProcessor接口的类,但不执行。
3.7initMessageSource
在Spring容器中初始化一些国际化相关的属性。
3.8initApplicationEventMulticaster
初始化ApplicationEventMulticaste(事件广播器)是在方法initApplicationEventMulticaster()中实现的,进入到方法体,如下:
protectedvoidinitApplicationEventMulticaster(){ ConfigurableListableBeanFactorybeanFactory=this.getBeanFactory(); //1、默认使用内置的事件广播器,如果有的话. //我们可以在配置文件中配置Spring事件广播器或者自定义事件广播器 //例如:if(beanFactory.containsLocalBean("applicationEventMulticaster")){ this.applicationEventMulticaster=(ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster",ApplicationEventMulticaster.class); if(this.logger.isTraceEnabled()){ this.logger.trace("UsingApplicationEventMulticaster["+this.applicationEventMulticaster+"]"); } }else{ //2、否则,新建一个事件广播器,SimpleApplicationEventMulticaster是spring的默认事件广播器 this.applicationEventMulticaster=newSimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton("applicationEventMulticaster",this.applicationEventMulticaster); if(this.logger.isTraceEnabled()){ this.logger.trace("No'applicationEventMulticaster'bean,using["+this.applicationEventMulticaster.getClass().getSimpleName()+"]"); } } }
通过源码可以看出该方法实现逻辑与initMessageSource基本相同,其步骤如下:查找是否有name为applicationEventMulticaster的bean,如果有则放到容器里,如果没有,初始化一个系统默认的SimpleApplicationEventMulticaster对象放入容器。
3.9onRefresh
模块方法,可用于refresh动作的扩展,默认为空实现。在SpringBoot中主要用于启动内嵌的Web服务器。
3.10registerListeners
注册监听器,找出系统中的ApplicationListener对象,注册到时间广播器中。如果有需要提前进行广播的事件,则执行广播。
protectedvoidregisterListeners(){ //首先,注册指定的静态事件监听器,在springboot中有应用 Iteratorvar1=this.getApplicationListeners().iterator(); while(var1.hasNext()){ ApplicationListener>listener=(ApplicationListener)var1.next(); this.getApplicationEventMulticaster().addApplicationListener(listener); } //其次,注册普通的事件监听器 String[]listenerBeanNames=this.getBeanNamesForType(ApplicationListener.class,true,false); String[]var7=listenerBeanNames; intvar3=listenerBeanNames.length; for(intvar4=0;var4earlyEventsToProcess=this.earlyApplicationEvents; this.earlyApplicationEvents=null; if(earlyEventsToProcess!=null){ Iteratorvar9=earlyEventsToProcess.iterator(); while(var9.hasNext()){ ApplicationEventearlyEvent=(ApplicationEvent)var9.next(); this.getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
3.11finishBeanFactoryInitialization
protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){ //判断有无ConversionService(bean属性类型转换服务接口),并初始化 if(beanFactory.containsBean("conversionService")&&beanFactory.isTypeMatch("conversionService",ConversionService.class)){ beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService",ConversionService.class)); } //如果beanFactory中不包含EmbeddedValueResolver,则向其中添加一个EmbeddedValueResolver if(!beanFactory.hasEmbeddedValueResolver()){//EmbeddedValueResolver-->解析bean中的占位符和表达式 beanFactory.addEmbeddedValueResolver((strVal)->{ returnthis.getEnvironment().resolvePlaceholders(strVal); }); } //初始化LoadTimeWeaverAware类型的bean //LoadTimeWeaverAware-->加载SpringBean时织入第三方模块,如AspectJ String[]weaverAwareNames=beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class,false,false); String[]var3=weaverAwareNames; intvar4=weaverAwareNames.length; for(intvar5=0;var5实例化BeanFactory中已经被注册但是未实例化的所有实例(懒加载的不需要实例化),主要操作是BeanFactory的preInstantiateSingletons方法。该方法分为两部分:
- 遍历已经解析出来的所有beanDefinitionNames,如果该BeanDefinition不是抽象类、是单例且没有设置懒加载,则进行实例化和初始化。
- 遍历解析出来的beanDefinitionNames,如果获得的单例是SmartInitializingSingleton的实现类,则会执行afterSingletonsInstantiated方法。注意该方法调用只会发生在启动阶段,后续懒加载对象再初始化的时候,不会再进行回调。
3.12finishRefresh
完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知。
总结
到此这篇关于SpringIoC学习之ApplicationContext中refresh过程详解的文章就介绍到这了,更多相关SpringApplicationContext中refresh过程内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。