Spring源码之容器的功能扩展和refresh方法解析
容器的功能扩展和refresh方法解析
在之前文章中我们了解了关于Spring中bean的加载流程,并一直使用BeanFactory接口以及它的默认实现类XmlBeanFactory,在Spring中还提供了另一个接口ApplicationContext,用于扩展BeanFactory中现有的功能。
首先BeanFactory和ApplicationContext都是用于加载bean的,但是相比之下,ApplicationContext提供了更多的扩展功能,ApplicationContext包含了BeanFactory的所有功能。通常我们会优先使用ApplicationContext。
我们来看看ApplicationContext多了哪些功能?
首先看一下写法上的不同。
使用BeanFactory方式加载XMLfinalBeanFactorybeanFactorynewXmlBeanFactory(newClassPathResource(springconfig。xml));
使用ApplicationContext方式加载XMLfinalApplicationContextapplicationContextnewClassPathXmlApplicationContext(springconfig。xml);
我们开始点开ClassPathXmlApplicationContext的构造函数,进行分析。publicClassPathXmlApplicationContext(StringconfigLocation)throwsBeansException{this(newString〔〕{configLocation},true,null);}publicClassPathXmlApplicationContext(String〔〕configLocations,booleanrefresh,NullableApplicationContextparent)throwsBeansException{super(parent);setConfigLocations(configLocations);if(refresh){refresh();}}
在ClassPathXmlApplicationContext中可以将配置文件路径以数组的形式传入,对解析及功能实现都在refresh()方法中实现。设置配置路径publicvoidsetConfigLocations(NullableString。。。locations){if(locations!null){Assert。noNullElements(locations,Configlocationsmustnotbenull);this。configLocationsnewString〔locations。length〕;for(inti0;ilocations。length;i){this。configLocations〔i〕resolvePath(locations〔i〕)。trim();}}else{this。configLocationsnull;}}
此函数主要解析给定的路径数组,如果数组中包含特殊符号,如{var},那么在resolvePath方法中会搜寻匹配的系统变量并替换。扩展功能
设置完路径后,就可以对文件进行解析和各种功能的实现,可以说在refresh方法中几乎包含了ApplicationContext中提供的全部功能,而且此函数的逻辑也十分清晰,可以很容易分析对应层次和逻辑。publicvoidrefresh()throwsBeansException,IllegalStateException{synchronized(this。startupShutdownMonitor){准备刷新的上下文环境,包括设置启动时间,是否激活标识位初始化属性源(propertysource)配置prepareRefresh();初始化BeanFactory并进行xml文件读取ConfigurableListableBeanFactorybeanFactoryobtainFreshBeanFactory();对BeanFactory进行各种功能填充prepareBeanFactory(beanFactory);try{子类覆盖方法做额外的处理postProcessBeanFactory(beanFactory);激活各种BeanFactory处理器invokeBeanFactoryPostProcessors(beanFactory);注册拦截bean创建的bean处理器,只是注册,具体调用在getBean中registerBeanPostProcessors(beanFactory);为上下文初始化Message源,国际化处理initMessageSource();初始化应用消息广播器,并放入applicationEventMulticasterbean中initApplicationEventMulticaster();留给子类来初始化其他的beanonRefresh();在所有注册的bean中查找Listenerbean,注册到消息广播器中registerListeners();初始化剩下的单例bean(非惰性)finishBeanFactoryInitialization(beanFactory);完成刷新过程,通知生命周期处理器LifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人finishRefresh();}catch(BeansExceptionex){if(logger。isWarnEnabled()){logger。warn(Exceptionencounteredduringcontextinitializationcancellingrefreshattempt:ex);}销毁已经初始化的singleton的Beans,以免有些bean会一直占用资源destroyBeans();重置活动标志cancelRefresh(ex);throwex;}finally{重置公共缓存resetCommonCaches();}}}
我们总结一下初始化的步骤。初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证初始化BeanFactory,并对XML文件进行读取。之前我们说过ClassPathXmlApplicationContext中包含着BeanFactory所提供的一切特征,那么在这一步将会复用BeanFactory中的配置文件读取解析及其他功能,在这一步之后ClassPathXmlApplicationContext就已经包含了BeanFactory所提供的功能,也就是可以对bean进行提取等操作对BeanFactory进行各种功能填充子类覆盖方法做额外的处理。主要用于我们在业务上做进一步扩展激活各种BeanFactory处理器注册拦截bean创建的bena处理器,这里仅仅是注册,真正调用在getBean中为上下文初始化Message源,对不同语言的消息体进行国际化处理初始化应用消息广播器,并放入applicationEventMulticasterbean中留给子类来初始化其他的bean在所有注册的bean中查找listenerbean,注册到消息广播器中初始化剩下的单实例(非惰性)完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent来通知别人环境准备
prepareRefresh方法主要做些准备工作,比如对系统属性及环境变量的初始化及验证。
initPropertySources
该方法里面是一个空实现,主要用于给我们根据需要去重写该方法,并在方法中进行个性化的属性处理及设置。protectedvoidinitPropertySources(){Forsubclasses:donothingbydefault。}validateRequiredProperties该方法主要对属性进行验证。默认情况下什么也没校验。在我们继承了ClassPathXmlApplicationContext类重写了initPropertySources方法后会进行相关校验。加载BeanFactory
obtainFreshBeanFactory方法主要用来获取BeanFactory,刚才说过ApplicationContext拥有BeanFactory的所有功能,这个方法就是实现BeanFactory的地方,也就是说调用完该方法后,applicationContext就拥有了BeanFactory的功能。protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){初始化BeanFactory,并进行XML文件读取,将得到的BeanFactory记录到当前实体属性中refreshBeanFactory();返回当前实体的beanFactory属性returngetBeanFactory();}protectedfinalvoidrefreshBeanFactory()throwsBeansException{if(hasBeanFactory()){destroyBeans();closeBeanFactory();}try{DefaultListableBeanFactorybeanFactorycreateBeanFactory();beanFactory。setSerializationId(getId());customizeBeanFactory(beanFactory);loadBeanDefinitions(beanFactory);synchronized(this。beanFactoryMonitor){this。beanFactorybeanFactory;}}catch(IOExceptionex){thrownewApplicationContextException(IOerrorparsingbeandefinitionsourceforgetDisplayName(),ex);}}
我们进入AbstractRefreshableApplicationContextrefreshBeanFactory()方法中。protectedfinalvoidrefreshBeanFactory()throwsBeansException{判断是否存在beanFactoryif(hasBeanFactory()){销毁所有单例destroyBeans();重置beanFactorycloseBeanFactory();}try{创建beanFactoryDefaultListableBeanFactorybeanFactorycreateBeanFactory();设置序列化idbeanFactory。setSerializationId(getId());定制beanFactory,设置相关属性,包括是否允许覆盖同名称不同定义的对象以及循环依赖customizeBeanFactory(beanFactory);初始化DocumentReader,进行XML读取和解析loadBeanDefinitions(beanFactory);synchronized(this。beanFactoryMonitor){this。beanFactorybeanFactory;}}catch(IOExceptionex){thrownewApplicationContextException(IOerrorparsingbeandefinitionsourceforgetDisplayName(),ex);}}
总结一下这个方法的流程:创建DefaultListableBeanFactory。声明方式为:BeanFactorybfnewXmlBeanFactory(beanFactoryTest。xml),其中的XmlBeanFactory继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader类型的reader属性,也就是说DefaultListableBeanFactory是容器的基础,必须首先实例化,这里就是实例化DefaultListableBeanFactory的步骤指定序列化ID定制BeanFactory加载BeanDefinition使用全局变量记录BeanFactory类实例定制BeanFactory
首先我们先了解customizeBeanFactory方法,该方法是在基本容器的基础上,增加了是否允许覆盖、是否允许扩展的设置。protectedvoidcustomizeBeanFactory(DefaultListableBeanFactorybeanFactory){如果不为空,设置beanFactory对象响应的属性,含义:是否允许覆盖同名称的不同定义的对象if(this。allowBeanDefinitionOverriding!null){beanFactory。setAllowBeanDefinitionOverriding(this。allowBeanDefinitionOverriding);}如果属性不为空,设置给beanFactory对象相应属性,含义:是否允许bean之间存在循环依赖if(this。allowCircularReferences!null){beanFactory。setAllowCircularReferences(this。allowCircularReferences);}}
具体这里只是做了简单的判断,具体设置属性的地方,使用子类覆盖即可。例如:author神秘杰克公众号:Java菜鸟程序员date2022612Description自定义ClassPathXmlApplicationContextpublicclassMyClassPathXmlApplicationContextextendsClassPathXmlApplicationContext{OverrideprotectedvoidcustomizeBeanFactory(DefaultListableBeanFactorybeanFactory){super。setAllowBeanDefinitionOverriding(false);super。setAllowCircularReferences(false);super。customizeBeanFactory(beanFactory);}}加载BeanDefinition
在初始化了DefaultListableBeanFactory后,我们还需要XmlBeanDefinitionReader来读取XML文件,这个步骤中首先要做的就是初始化XmlBeanDefinitionReader。protectedvoidloadBeanDefinitions(DefaultListableBeanFactorybeanFactory)throwsBeansException,IOException{为指定beanFactory创建XmlBeanDefinitionReaderXmlBeanDefinitionReaderbeanDefinitionReadernewXmlBeanDefinitionReader(beanFactory);进行环境变量的设置beanDefinitionReader。setEnvironment(this。getEnvironment());beanDefinitionReader。setResourceLoader(this);beanDefinitionReader。setEntityResolver(newResourceEntityResolver(this));对beanDefinitionReader进行设置,可以覆盖initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);}
初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader后,我们就可以进行配置文件的读取了。最终XmlBeanDefinitionReader所去读的BeanDefinitionHolder都会注册到DefaultListableBeanFactory中。
经过该方法后类型为DefaultListableBeanFactory中的变量beanFactory已经包含了所有解析好的配置。关于配置文件的读取这一部分之前文章已经讲过,这里就不再赘述。功能扩展
我们在完成了配置文件解析后,我们接着进入prepareBeanFactory方法。protectedvoidprepareBeanFactory(ConfigurableListableBeanFactorybeanFactory){设置beanFactory的ClassLoader为当前context的ClassLoaderbeanFactory。setBeanClassLoader(getClassLoader());设置beanFactory的表达式语言处理beanFactory。setBeanExpressionResolver(newStandardBeanExpressionResolver(beanFactory。getBeanClassLoader()));为beanFactory增加了一个默认的propertyEditor,主要是对bean的属性等设置管理的一个工具beanFactory。addPropertyEditorRegistrar(newResourceEditorRegistrar(this,getEnvironment()));添加BeanPostProcessorbeanFactory。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。registerResolvableDependency(BeanFactory。class,beanFactory);beanFactory。registerResolvableDependency(ResourceLoader。class,this);beanFactory。registerResolvableDependency(ApplicationEventPublisher。class,this);beanFactory。registerResolvableDependency(ApplicationContext。class,this);增加了ApplicationListenerDetector主要是检测bean是否实现了ApplicationListener接口beanFactory。addBeanPostProcessor(newApplicationListenerDetector(this));增加对AspectJ的支持if(beanFactory。containsBean(LOADTIMEWEAVERBEANNAME)){beanFactory。addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory));SetatemporaryClassLoaderfortypematching。beanFactory。setTempClassLoader(newContextTypeMatchClassLoader(beanFactory。getBeanClassLoader()));}添加默认的系统环境beanif(!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());}}
该方法主要做了几个方面的扩展:增加了对SpEL语言的支持增加了对属性编辑器的支持增加了一些内置类,比如EnvironmentAware、MessageSourceAware的信息注入设置了依赖功能可忽略的接口注册了一些固定依赖的属性增加AspectJ的支持将相关环境变量及属性注册以单例模式注册BeanFactory的后处理
BeanFactory作为Spring中容器的基础,用于存放所有已经加载的bean,为了保证程序的高扩展性,Spring针对BeanFactory做了大量的扩展,比如PostProcessor等都是在这里实现的。激活注册的BeanFactoryPostProcessor
在学习之前,我们先了解一下BeanFactoryPostProcessor的用法。BeanFactoryPostProcessor接口和BeanPostProcessor类似,可以对bean的定义进行处理。也就是说,SpringIOC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取配置元数据,并可以修改它。BeanFactoryPostProcessor可以配置多个,通过实现Ordered接口设置order来控制执行顺序。
需要注意的是如果在容器中定义一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后置处理。BeanFactoryPostProcessor不会对其他容器中的bean进行后置处理。
1。BeanFactoryPostProcessor的典型应用:PropertySourcesPlaceholderConfigurer
首先我们来看一下配置文件:beanidhelloclasscn。jack。Hellopropertynamemsgvalue{bean。msg}valuepropertybean
在里面我们使用到了变量引用:{bean。msg},这就是Spring的分散配置,我们可以在配置文件中配置该属性的值。
application。propertiesbean。msghi
然后我们再进行配置文件的配置。beanidhelloHandlerclassorg。springframework。context。support。PropertySourcesPlaceholderConfigurerpropertynamelocationslistvalueapplication。propertiesvaluelistpropertybean
这时候就明白了,我们通过PreferencesPlaceholderConfigurer中进行获取我们的配置信息。我们查看该类可以知道间接性继承了BeanFactoryPostProcessor接口。
当Spring加载任何实现了这个接口的bean时,都会在bean工厂加载所有bena的配置之后执行postProcessBeanFactory方法。在方法中先后调用了mergeProperties、convertProperties、processProperties这三个方法,分别得到配置、将得到的配置进行转换为合适的类型、最后将配置内容告知BeanFactory。
正是通过实现BeanFactoryPostProcessor,BeanFactory会在实例化任何bean之前获得配置信息,从而能够正确解析bean配置文件中的变量引用。
PropertySourcesPlaceholderConfigurer已经取代了PropertyPlaceholderConfigurer,因为汇聚了Environment、多个PropertySource。所以它能够控制取值优先级、顺序,并且还提供了访问的方法,后期再想获取也不是问题。
2。使用自定义BeanFactoryPostProcessor
我们自己实现一个自定义BeanFactoryPostProcessor,去除我们不想要显示的属性值的功能来展示自定义BeanFactoryPostProcessor的创建及使用,例如bean定义中我们屏蔽掉‘guapi’、‘shazi’。beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdbeanclasscn。jack。ObscenityRemovingBeanFactoryPostProcessoridcustomBeanFactoryPostProcessorpropertynameobscenitiessetvalueguapivaluevalueshazivaluesetpropertybeanbeanclasscn。jack。SimpleBeanidsimpleBeanpropertynameuserNamevaluejackpropertynameaddressvalueguapipropertynameemailvalueshazibeanbeanspublicclassSimpleBean{privateStringuserName;privateStringemail;privateStringaddress;gettersetter}publicclassObscenityRemovingBeanFactoryPostProcessorimplementsBeanFactoryPostProcessor{privatefinalSetStringobscenities;publicObscenityRemovingBeanFactoryPostProcessor(){this。obscenitiesnewHashSet();}将所有bean的参数中含有obscenities集合中的值进行屏蔽OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{String〔〕beanNamesbeanFactory。getBeanDefinitionNames();for(StringbeanName:beanNames){finalBeanDefinitionbeanDefinitionbeanFactory。getBeanDefinition(beanName);StringValueResolvervalueResolverstrVal{if(isObscene(strVal)){return;}returnstrVal;};finalBeanDefinitionVisitorbeanDefinitionVisitornewBeanDefinitionVisitor(valueResolver);beanDefinitionVisitor。visitBeanDefinition(beanDefinition);}}publicbooleanisObscene(Objectvalue){StringpotentialObscenityvalue。toString()。toUpperCase();returnthis。obscenities。contains(potentialObscenity);}publicvoidsetObscenities(SetStringobscenities){this。obscenities。clear();for(Stringobscenity:obscenities){this。obscenities。add(obscenity。toUpperCase());}}}
启动类:publicclassTest{publicstaticvoidmain(String〔〕args){ApplicationContextacnewClassPathXmlApplicationContext(beanFactory。xml);SimpleBeansimpleBean(SimpleBean)ac。getBean(simpleBean);System。out。println(simpleBean);}}
输出结果:SimpleBean{userNamejack,email,address}
我们通过ObscenityRemovingBeanFactoryPostProcessor我们很好的屏蔽掉了我们不想要显示的属性。激活BeanFactoryPostProcessor
我们在了解了BeanFactoryPostProcessor的用法之后就可以继续回到我们的refresh方法中继续研究源码了。
进入invokeBeanFactoryPostProcessors方法中。protectedvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory){PostProcessorRegistrationDelegate。invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors());DetectaLoadTimeWeaverandprepareforweaving,iffoundinthemeantime(e。g。throughanBeanmethodregisteredbyConfigurationClassPostProcessor)if(beanFactory。getTempClassLoader()nullbeanFactory。containsBean(LOADTIMEWEAVERBEANNAME)){beanFactory。addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory));beanFactory。setTempClassLoader(newContextTypeMatchClassLoader(beanFactory。getBeanClassLoader()));}}
我们继续进入具体重载方法中invokeBeanFactoryPostProcessors。publicstaticvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory,ListBeanFactoryPostProcessorbeanFactoryPostProcessors){将已经执行过的BeanFactoryPostProcessor存储在processedBeans,防止重复执行SetStringprocessedBeansnewHashSet();对BeanDefinitionRegistry类型进行处理if(beanFactoryinstanceofBeanDefinitionRegistry){BeanDefinitionRegistryregistry(BeanDefinitionRegistry)beanFactory;用来存放BeanFactoryPostProcessor对象ListBeanFactoryPostProcessorregularPostProcessorsnewArrayList();用来存放BeanDefinitionRegistryPostProcessor对象方便统一执行实现了BeanDefinitionRegistryPostProcessor接口父类的方法ListBeanDefinitionRegistryPostProcessorregistryProcessorsnewArrayList();处理外部定义的BeanFactoryPostProcessor,将BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor区分开for(BeanFactoryPostProcessorpostProcessor:beanFactoryPostProcessors){if(postProcessorinstanceofBeanDefinitionRegistryPostProcessor){BeanDefinitionRegistryPostProcessorregistryProcessor(BeanDefinitionRegistryPostProcessor)postProcessor;对于BeanDefinitionRegistryPostProcessor类型,需要先调用此方法,再添加到集合中registryProcessor。postProcessBeanDefinitionRegistry(registry);registryProcessors。add(registryProcessor);}else{记录常规BeanFactoryPostProcessorregularPostProcessors。add(postProcessor);}}存放当前需要执行的BeanDefinitionRegistryPostProcessorListBeanDefinitionRegistryPostProcessorcurrentRegistryProcessorsnewArrayList();调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessor。获取所有实现了BeanDefinitionRegistryPostProcessor接口的类名String〔〕postProcessorNamesbeanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class,true,false);for(StringppName:postProcessorNames){判断当前类是否实现了PriorityOrdered接口if(beanFactory。isTypeMatch(ppName,PriorityOrdered。class)){将BeanDefinitionRegistryPostProcessor类型存入currentRegistryProcessors中currentRegistryProcessors。add(beanFactory。getBean(ppName,BeanDefinitionRegistryPostProcessor。class));提前存放到processedBeans,避免重复执行,但是此处还未执行processedBeans。add(ppName);}}对currentRegistryProcessors集合中的BeanDefinitionRegistryPostProcessor类型进行排序sortPostProcessors(currentRegistryProcessors,beanFactory);添加到registryProcessors集合,用于后续执行父接口的postProcessBeanFactory方法registryProcessors。addAll(currentRegistryProcessors);遍历集合,执行BeanDefinitionRegistryPostProcessor。postProcessBeanDefinitionRegistry()方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);执行完毕后清空该集合currentRegistryProcessors。clear();接着,调用实现Ordered的BeanDefinitionRegistryPostProcessors这里再次获取BeanDefinitionRegistryPostProcessor,是因为有可能在上面方法执行过程中添加了BeanDefinitionRegistryPostProcessor而下面处理BeanFactoryPostProcessor的时候又不需要重复获取了是为什么呢?因为添加BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor只能在BeanDefinitionRegistryPostProcessor中添加,在BeanFactoryPostProcessor是无法添加的for(StringppName:postProcessorNames){判断当前bean没有被执行过,并且实现了Ordered接口if(!processedBeans。contains(ppName)beanFactory。isTypeMatch(ppName,Ordered。class)){如果BeanFactory中没有该Bean则会去创建该BeancurrentRegistryProcessors。add(beanFactory。getBean(ppName,BeanDefinitionRegistryPostProcessor。class));processedBeans。add(ppName);}}sortPostProcessors(currentRegistryProcessors,beanFactory);registryProcessors。addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);currentRegistryProcessors。clear();最后处理没有实现Ordered与PriorityOrdered接口的BeanDefinitionRegistryPostProcessorbooleanreiteratetrue;while(reiterate){reiteratefalse;再次获取BeanDefinitionRegistryPostProcessorpostProcessorNamesbeanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class,true,false);for(StringppName:postProcessorNames){if(!processedBeans。contains(ppName)){将本次要执行的BeanDefinitionRegistryPostProcessor存放到currentRegistryProcessorscurrentRegistryProcessors。add(beanFactory。getBean(ppName,BeanDefinitionRegistryPostProcessor。class));processedBeans。add(ppName);reiteratetrue;}}sortPostProcessors(currentRegistryProcessors,beanFactory);registryProcessors。addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry);currentRegistryProcessors。clear();}现在,调用到目前为止处理的所有处理器的postProcessBeanFactory回调。invokeBeanFactoryPostProcessors(registryProcessors,beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors,beanFactory);}else{BeanFactory如果不归属于BeanDefinitionRegistry类型,则直接执行beanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactoryPostProcessors,beanFactory);}String〔〕postProcessorNamesbeanFactory。getBeanNamesForType(BeanFactoryPostProcessor。class,true,false);用于存放实现了priorityOrdered接口的BeanFactoryPostProcessorListBeanFactoryPostProcessorpriorityOrderedPostProcessorsnewArrayList();用于存放实现了ordered接口的BeanFactoryPostProcessor名称ListStringorderedPostProcessorNamesnewArrayList();用于存放无排序的BeanFactoryPostProcessor名称ListStringnonOrderedPostProcessorNamesnewArrayList();for(StringppName:postProcessorNames){如果已经执行过了,则不做处理if(processedBeans。contains(ppName)){skipalreadyprocessedinfirstphaseabove}如果实现了PriorityOrdered则添加elseif(beanFactory。isTypeMatch(ppName,PriorityOrdered。class)){priorityOrderedPostProcessors。add(beanFactory。getBean(ppName,BeanFactoryPostProcessor。class));}如果实现了Ordered则添加elseif(beanFactory。isTypeMatch(ppName,Ordered。class)){orderedPostProcessorNames。add(ppName);}如果没有排序则添加到指定集合else{nonOrderedPostProcessorNames。add(ppName);}}首先调用实现PriorityOrdered的BeanFactoryPostProcessor。sortPostProcessors(priorityOrderedPostProcessors,beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors,beanFactory);然后调用实现Ordered的BeanFactoryPostProcessors。ListBeanFactoryPostProcessororderedPostProcessorsnewArrayList(orderedPostProcessorNames。size());for(StringpostProcessorName:orderedPostProcessorNames){orderedPostProcessors。add(beanFactory。getBean(postProcessorName,BeanFactoryPostProcessor。class));}sortPostProcessors(orderedPostProcessors,beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors,beanFactory);最后调用其他没有排序的BeanFactoryPostProcessor。ListBeanFactoryPostProcessornonOrderedPostProcessorsnewArrayList(nonOrderedPostProcessorNames。size());for(StringpostProcessorName:nonOrderedPostProcessorNames){nonOrderedPostProcessors。add(beanFactory。getBean(postProcessorName,BeanFactoryPostProcessor。class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors,beanFactory);清空缓存beanFactory。clearMetadataCache();}注册BeanPostProcessor
了解了BeanFactoryPostProcessors的调用后,我们现在来了解下BeanPostProcessor,这里仅仅是注册,并不是调用。真正的调用在bean实例化阶段进行的。
在BeanFactory中并没有实现后处理器的自动注册功能,所以在调用的时候如果没有进行主动注册则是不能够使用的。但是在ApplicationContext中添加了主动注册功能。
比如自定义这样的后处理器:publicclassMyInstantiationAwareBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{OverridepublicObjectpostProcessBeforeInstantiation(Classlt;?beanClass,StringbeanName)throwsBeansException{System。out。println();returnnull;}}beanclasscn。jack。MyInstantiationAwareBeanPostProcessor
在使用ApplicationContext方式获取bean的时候会在获取之前打印出,在BeanFactory方式进行bean的加载是不会有该打印的。
这个特性就是在registerBeanPostProcessors中实现的。publicstaticvoidregisterBeanPostProcessors(ConfigurableListableBeanFactorybeanFactory,AbstractApplicationContextapplicationContext){获取所有实现BeanPostProcessor接口的类String〔〕postProcessorNamesbeanFactory。getBeanNamesForType(BeanPostProcessor。class,true,false);注册一个BeanPostProcessorChecker,用来记录bean在BeanPostProcessor实例化时的信息intbeanProcessorTargetCountbeanFactory。getBeanPostProcessorCount()1postProcessorNames。length;beanFactory。addBeanPostProcessor(newBeanPostProcessorChecker(beanFactory,beanProcessorTargetCount));区分实现不同接口的BeanPostProcessorsListBeanPostProcessorpriorityOrderedPostProcessorsnewArrayList();ListBeanPostProcessorinternalPostProcessorsnewArrayList();ListStringorderedPostProcessorNamesnewArrayList();ListStringnonOrderedPostProcessorNamesnewArrayList();根据不同类型进行addfor(StringppName:postProcessorNames){if(beanFactory。isTypeMatch(ppName,PriorityOrdered。class)){BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);priorityOrderedPostProcessors。add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors。add(pp);}}elseif(beanFactory。isTypeMatch(ppName,Ordered。class)){orderedPostProcessorNames。add(ppName);}else{nonOrderedPostProcessorNames。add(ppName);}}排序后执行注册实现了PriorityOrdered的BeanPostProcessorssortPostProcessors(priorityOrderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,priorityOrderedPostProcessors);注册实现Ordered接口的BeanPostProcessorsListBeanPostProcessororderedPostProcessorsnewArrayList(orderedPostProcessorNames。size());for(StringppName:orderedPostProcessorNames){拿到ppName对应的BeanPostProcessor实例对象BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);将ppName对应的BeanPostProcessor实例对象添加到orderedPostProcessors,准备执行注册orderedPostProcessors。add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){如果ppName对应的bean实例也实现了MergedBeanDefinitionPostProcessor接口,则添加到该集合中internalPostProcessors。add(pp);}}对orderedPostProcessors进行排序并注册sortPostProcessors(orderedPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,orderedPostProcessors);注册所有常规的BeanPostProcessors,过程同上ListBeanPostProcessornonOrderedPostProcessorsnewArrayList(nonOrderedPostProcessorNames。size());for(StringppName:nonOrderedPostProcessorNames){BeanPostProcessorppbeanFactory。getBean(ppName,BeanPostProcessor。class);nonOrderedPostProcessors。add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){internalPostProcessors。add(pp);}}registerBeanPostProcessors(beanFactory,nonOrderedPostProcessors);注册所有mergedBeanDefinitionPostProcessor类型的BeanPostProcessor,并非重复注册在beanFactory。addBeanPostProcessor中会先移除已经存在的BeanPostProcessorsortPostProcessors(internalPostProcessors,beanFactory);registerBeanPostProcessors(beanFactory,internalPostProcessors);添加ApplicationListener探测器beanFactory。addBeanPostProcessor(newApplicationListenerDetector(applicationContext));}初始化消息资源
在initMessageSource中主要功能是提取配置文件中的messageSource,并将其记录在Spring容器中,也就是ApplicationContext中。如果用户未设置资源文件的话,则获取Spring默认的配置delegatingMessageSource。protectedvoidinitMessageSource(){ConfigurableListableBeanFactorybeanFactorygetBeanFactory();Bean的名称必须要是messageSourceif(beanFactory。containsLocalBean(MESSAGESOURCEBEANNAME)){MESSAGESOURCEBEANNAMEmessageSourcethis。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。isTraceEnabled()){logger。trace(UsingMessageSource〔this。messageSource〕);}}else{如果用户并没有定义配置文件,那么使用临时的DelegatingMessageSource以便于作为调用getMessage的返回DelegatingMessageSourcedmsnewDelegatingMessageSource();dms。setParentMessageSource(getInternalParentMessageSource());this。messageSourcedms;beanFactory。registerSingleton(MESSAGESOURCEBEANNAME,this。messageSource);if(logger。isTraceEnabled()){logger。trace(NoMESSAGESOURCEBEANNAMEbean,using〔this。messageSource〕);}}}
这里规定资源文件必须为messageSource,否则就会获取不到自定义资源配置。初始化ApplicationEventMulticaster
initApplicationEventMulticaster方法实现比较简单,存在两种情况:如果用户自定义了事件广播器,那么就是用用户自定义的事件广播器如果用户没有自定义事件广播器,那么使用默认的ApplicationEventMulticasterprotectedvoidinitApplicationEventMulticaster(){ConfigurableListableBeanFactorybeanFactorygetBeanFactory();判断容器中是否存在BeanDefinitionName为applicationEventMulticaster的bd,也就是自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口if(beanFactory。containsLocalBean(APPLICATIONEVENTMULTICASTERBEANNAME)){this。applicationEventMulticasterbeanFactory。getBean(APPLICATIONEVENTMULTICASTERBEANNAME,ApplicationEventMulticaster。class);if(logger。isTraceEnabled()){logger。trace(UsingApplicationEventMulticaster〔this。applicationEventMulticaster〕);}}else{如果没有,则默认采用SimpleApplicationEventMulticasterthis。applicationEventMulticasternewSimpleApplicationEventMulticaster(beanFactory);beanFactory。registerSingleton(APPLICATIONEVENTMULTICASTERBEANNAME,this。applicationEventMulticaster);if(logger。isTraceEnabled()){logger。trace(NoAPPLICATIONEVENTMULTICASTERBEANNAMEbean,using〔this。applicationEventMulticaster。getClass()。getSimpleName()〕);}}}
最后,作为广播器,一定是用于存放监听器并在合适的时候调用监听器,我们进入默认的广播器实现类SimpleApplicationEventMulticaster中看一下。
看到如下方法:publicvoidmulticastEvent(finalApplicationEventevent,NullableResolvableTypeeventType){ResolvableTypetype(eventType!null?eventType:resolveDefaultEventType(event));ExecutorexecutorgetTaskExecutor();for(ApplicationListenerlt;?listener:getApplicationListeners(event,type)){if(executor!null){executor。execute(()invokeListener(listener,event));}else{invokeListener(listener,event);}}}
可以推断,当产生Spring事件的时候会默认使用SimpleApplicationEventMulticaster的multicastEvent来广播事件,遍历所有监听器,并使用监听器中的onApplicationEvent方法来进行监听器的处理。而对于每个监听器来说其实都可以获取到产生的事件,但是是否进行处理则由事件监听器决定。注册监听器
我们反复提到了监听器,我们接下来看一下Spring注册监听器的时候又做了哪些逻辑操作?protectedvoidregisterListeners(){首先注册静态的指定的监听器,注册的是特殊的事件监听器,而不是配置中的beanfor(ApplicationListenerlt;?listener:getApplicationListeners()){getApplicationEventMulticaster()。addApplicationListener(listener);}这里不会初始化FactoryBean,我们需要保留所有的普通bean不会实例化这些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);}}}
只是将一些特殊的监听器注册到广播组中,那些在bean配置文件中实现了ApplicationListener接口的类还没有实例化,所以此时只是将name保存到了广播组中,将这些监听器注册到广播组中的操作时在bean的后置处理器中完成的,那时候bean的实例化已经完成了。初始化非延迟加载单例
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){初始化此上下文的转换服务if(beanFactory。containsBean(CONVERSIONSERVICEBEANNAME)beanFactory。isTypeMatch(CONVERSIONSERVICEBEANNAME,ConversionService。class)){beanFactory。setConversionService(beanFactory。getBean(CONVERSIONSERVICEBEANNAME,ConversionService。class));}如果beanFactory之前没有注册解析器,则注册默认的解析器,例如{}解析成真正的属性:主要用于注解属性值的解析if(!beanFactory。hasEmbeddedValueResolver()){beanFactory。addEmbeddedValueResolver(strValgetEnvironment()。resolvePlaceholders(strVal));}处理EnableLoadTimeWeaving或context:loadtimeweaver标记的类String〔〕weaverAwareNamesbeanFactory。getBeanNamesForType(LoadTimeWeaverAware。class,false,false);for(StringweaverAwareName:weaverAwareNames){getBean(weaverAwareName);}临时类加载器设置为空beanFactory。setTempClassLoader(null);冻结所有的bean定义,说明注册的bean定义将不被修改或者进一步处理beanFactory。freezeConfiguration();初始化剩下的单例实例(非惰性)beanFactory。preInstantiateSingletons();}
首先,我们先了解下ConversionService类所提供的作用。
1。ConversionService的设置
之前我们提到可以用自定义类型转换器把String类型转换为Date,在Spring中也提供了使用Converter来进行转换。
2。冻结配置
冻结所有的bean定义,说明注册的bean定义将不被修改或者进行任何一步的处理。publicvoidfreezeConfiguration(){this。configurationFrozentrue;this。frozenBeanDefinitionNamesStringUtils。toStringArray(this。beanDefinitionNames);}
3。初始化延迟加载
ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化也就意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有单例bean,这个实例化过程就是在finishBeanFactoryInitialization方法中的preInstantiateSingletons方法中完成的。publicvoidpreInstantiateSingletons()throwsBeansException{if(logger。isTraceEnabled()){logger。trace(Preinstantiatingsingletonsinthis);}创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义ListStringbeanNamesnewArrayList(this。beanDefinitionNames);遍历beanNames,触发所有非懒加载单例bean的初始化for(StringbeanName:beanNames){获取beanName对应的MergedBeanDefinitionRootBeanDefinitionbdgetMergedLocalBeanDefinition(beanName);bd对应的不是抽象类并且是单例并且不是懒加载if(!bd。isAbstract()bd。isSingleton()!bd。isLazyInit()){判断是否为FactoryBeanif(isFactoryBean(beanName)){通过前缀和beanName拿到BeanObjectbeangetBean(FACTORYBEANPREFIXbeanName);如果为FactoryBeanif(beaninstanceofFactoryBean){finalFactoryBeanlt;?factory(FactoryBeanlt;?)bean;判断这个FactoryBean是否希望急切的初始化booleanisEagerInit;if(System。getSecurityManager()!nullfactoryinstanceofSmartFactoryBean){isEagerInitAccessController。doPrivileged((PrivilegedActionBoolean)((SmartFactoryBeanlt;?)factory)::isEagerInit,getAccessControlContext());}else{isEagerInit(factoryinstanceofSmartFactoryBean((SmartFactoryBeanlt;?)factory)。isEagerInit());}如果希望急切的初始化,则通过beanName获取bean实例if(isEagerInit){getBean(beanName);}}}else{如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例getBean(beanName);}}}遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调for(StringbeanName:beanNames){拿到beanName对应的bean实例ObjectsingletonInstancegetSingleton(beanName);判断singletonInstance是否实现了SmartInitializingSingleton接口if(singletonInstanceinstanceofSmartInitializingSingleton){finalSmartInitializingSingletonsmartSingleton(SmartInitializingSingleton)singletonInstance;触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法if(System。getSecurityManager()!null){AccessController。doPrivileged((PrivilegedActionObject)(){smartSingleton。afterSingletonsInstantiated();returnnull;},getAccessControlContext());}else{smartSingleton。afterSingletonsInstantiated();}}}}finishRefresh
在Spring中提供了Lifecycle接口,该接口包含startstop方法,实现此接口后Spring会保证在启动时候调用其start方法开始声明周期,并在Spring关闭时候调用stop方法来结束声明周期。通常用来配置后台程序,在启动后一直运行(比如MQ)而ApplicationContext最后一步finishRefresh方法就是实现这一功能。protectedvoidfinishRefresh(){清除资源缓存clearResourceCaches();1。为此上下文初始化生命周期处理器initLifecycleProcessor();2。首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法)getLifecycleProcessor()。onRefresh();3。推送上下文刷新完毕事件到相应的监听器publishEvent(newContextRefreshedEvent(this));ParticipateinLiveBeansViewMBean,ifactive。LiveBeansView。registerApplicationContext(this);}
1。initLifecycleProcessor
当ApplicationContext启动或停止时,它会通过LifecycleProcessor来和所有声明的bean的周期做状态更新,而在LifecycleProcessor的使用前首先进行初始化。protectedvoidinitLifecycleProcessor(){ConfigurableListableBeanFactorybeanFactorygetBeanFactory();判断BeanFactory是否已经存在生命周期处理器(beanNamelifecycleProcessor)if(beanFactory。containsLocalBean(LIFECYCLEPROCESSORBEANNAME)){this。lifecycleProcessorbeanFactory。getBean(LIFECYCLEPROCESSORBEANNAME,LifecycleProcessor。class);if(logger。isTraceEnabled()){logger。trace(UsingLifecycleProcessor〔this。lifecycleProcessor〕);}}else{如果不存在,则使用DefaultLifecycleProcessorDefaultLifecycleProcessordefaultProcessornewDefaultLifecycleProcessor();defaultProcessor。setBeanFactory(beanFactory);this。lifecycleProcessordefaultProcessor;并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中beanFactory。registerSingleton(LIFECYCLEPROCESSORBEANNAME,this。lifecycleProcessor);if(logger。isTraceEnabled()){logger。trace(NoLIFECYCLEPROCESSORBEANNAMEbean,using〔this。lifecycleProcessor。getClass()。getSimpleName()〕);}}}
2。onRefresh
启动所有实现了Lifecycle接口的beanpublicvoidonRefresh(){startBeans(true);this。runningtrue;}privatevoidstartBeans(booleanautoStartupOnly){MapString,LifecyclelifecycleBeansgetLifecycleBeans();MapInteger,LifecycleGroupphasesnewHashMap();lifecycleBeans。forEach((beanName,bean){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(beanName,bean);}});if(!phases。isEmpty()){ListIntegerkeysnewArrayList(phases。keySet());Collections。sort(keys);for(Integerkey:keys){phases。get(key)。start();}}}
3。publishEvent
当完成ApplicationContext初始化的时候,要通过Spring中的发布机制来发出ContextRefreshedEvent事件,以保证对应的监听器可以做进一步的逻辑处理。protectedvoidpublishEvent(Objectevent,NullableResolvableTypeeventType){Assert。notNull(event,Eventmustnotbenull);如有必要,将事件装饰为ApplicationEventApplicationEventapplicationEvent;if(eventinstanceofApplicationEvent){applicationEvent(ApplicationEvent)event;}else{applicationEventnewPayloadApplicationEvent(this,event);if(eventTypenull){eventType((PayloadApplicationEventlt;?)applicationEvent)。getResolvableType();}}Multicastrightnowifpossibleorlazilyoncethemulticasterisinitializedif(this。earlyApplicationEvents!null){this。earlyApplicationEvents。add(applicationEvent);}else{使用事件广播器广播事件到相应的监听器getApplicationEventMulticaster()。multicastEvent(applicationEvent,eventType);}通过parent发布事件if(this。parent!null){if(this。parentinstanceofAbstractApplicationContext){((AbstractApplicationContext)this。parent)。publishEvent(event,eventType);}else{this。parent。publishEvent(event);}}}
到这里,refresh方法就解析完成了。下一步就是AOP了。
如果本文对你有帮助,别忘记给我个3连,点赞,转发,评论,
咱们下期见!答案获取方式:已赞已评已关
学习更多JAVA知识与技巧,关注与私信博主(03)
原文出处:https:segmentfault。coma1190000041999221