spring初始化源碼代碼淺析
前言
在《spring初始化源碼淺析之關(guān)鍵類(lèi)和擴(kuò)展接口》中主要是關(guān)鍵類(lèi)和擴(kuò)展接口的介紹,本文主要是debug代碼來(lái)看spring是如何初始化以及在分別在何時(shí)輸出上文 demo中各擴(kuò)展點(diǎn)的日志。
本文分為兩部分:《spring初始化源碼淺析之關(guān)鍵類(lèi)和擴(kuò)展接口》、《spring初始化源碼淺析之代碼淺析》
1、refresh()簡(jiǎn)介
通過(guò)ClassPathXmlApplicationContext構(gòu)造方法進(jìn)入 refresh方法
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //容器刷新前做一些準(zhǔn)備工作 prepareRefresh(); // 創(chuàng)建DefaultListableBeanFactory對(duì)象,解析出所有BeanDefinition信息, //注冊(cè)緩存在DefaultListableBeanFactory的beanDefinitionMap屬性中,供后面創(chuàng)建bean對(duì)象時(shí)使用 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 為beanFactory提供一些標(biāo)準(zhǔn)配置,如:類(lèi)加載器、環(huán)境變量等 prepareBeanFactory(beanFactory); try { // 為beanFactory提供一些個(gè)性配置,通過(guò)在子上下文中復(fù)寫(xiě)該方法來(lái)實(shí)現(xiàn) postProcessBeanFactory(beanFactory); //創(chuàng)建實(shí)現(xiàn)BeanFactoryPostProcessor的實(shí)現(xiàn)類(lèi),并執(zhí)行接口的方法。 //該方法執(zhí)行完后會(huì)輸出實(shí)例中的1-7步的日志 invokeBeanFactoryPostProcessors(beanFactory); //創(chuàng)建BeanPostProcessor的實(shí)現(xiàn)類(lèi),并注冊(cè)到BeanFactoryPostProcessor的beanPostProcessors列表中, //在后面創(chuàng)建普通非lazy對(duì)象時(shí)會(huì)遍歷該列表回調(diào)前置和后置方法 registerBeanPostProcessors(beanFactory); //跟國(guó)際化消息相關(guān),沒(méi)去研究過(guò) initMessageSource(); //初始化該上下文的事件廣播 initApplicationEventMulticaster(); //模板方法,在不同的容器刷新的時(shí)候可以自定義邏輯 onRefresh(); //創(chuàng)建ApplicationListener的實(shí)現(xiàn)類(lèi),并注冊(cè)到該上下文中 registerListeners(); //完成所有剩余的非lazy的bean的創(chuàng)建 finishBeanFactoryInitialization(beanFactory); //上下文的創(chuàng)建完成的一些設(shè)置和緩存清理,并發(fā)布創(chuàng)建完成事件 finishRefresh(); }catch (BeansException ex) { …… }finally { //Reset common introspection caches in Spring's core, since we //might not ever need metadata for singleton beans anymore... resetCommonCaches(); } }
2、關(guān)鍵代碼跟蹤
先看《spring初始化源碼淺析之關(guān)鍵類(lèi)和擴(kuò)展接口》文中代碼執(zhí)行結(jié)果:
2.1、obtainFreshBeanFactory()代碼分析
首先找到beanFactory的入口方法,如下
繼續(xù)debug進(jìn)入refreshBeanFactory方法,如下
從下圖中可以看到,XmlBeanDefinitionReader為加載BeanDefinition的關(guān)鍵類(lèi),而將beanFactoy作為構(gòu)造參數(shù)主要是為了將創(chuàng)建好的BeanDefinition對(duì)象注冊(cè)到beanFactory中,后面會(huì)貼出相應(yīng)的代碼,如下
繼續(xù)斷點(diǎn)進(jìn)入XmlBeanDefinitionReader的loadBeanDefinitions方法,可見(jiàn)入?yún)閙ain方法中的指定配置文件的名稱(chēng),如下
斷點(diǎn)繼續(xù)走,跳過(guò)將applicationContext.xml文件解析成Document的過(guò)程,進(jìn)入registerBeanDefinitions(Document doc, Resource resource)方法,入?yún)閍pplicationContext.xml對(duì)應(yīng)的Document對(duì)象,該方法構(gòu)造一個(gè)BeanDefinitionDocumentReader對(duì)象來(lái)具體的負(fù)責(zé)從doc對(duì)象創(chuàng)建BeanDefinition對(duì)象,并注冊(cè)到beanFactory中,如下
注意 BeanDefinitionDocumentReader的registerBeanDefinitions方法一個(gè)入?yún)閄mlReaderContext對(duì)象,該對(duì)象的reader即為前面創(chuàng)建XmlBeanDefinitionReader對(duì)象。
繼續(xù)斷點(diǎn)進(jìn)入以下方法:
最后進(jìn)入DefaultListableBeanFactory的registerBeanDefinition方法,最后將創(chuàng)建好的BeanDefinition對(duì)象緩存到DefaultListableBeanFactory的一個(gè)ConcurrentHashMap中
最終將配置文件中所有的bean配置轉(zhuǎn)成BeanDefinition對(duì)象緩存起來(lái),供后面創(chuàng)建具體的bean對(duì)象使用。
2.2、invokeBeanFactoryPostProcessors(beanFactory)代碼分析
進(jìn)入方法發(fā)現(xiàn)邏輯都交給PostProcessorRegistrationDelegate類(lèi)來(lái)處理:
斷點(diǎn)一直走到下面方法,先嘗試從單利的緩存中去找,找不到再通過(guò)單例工廠類(lèi)創(chuàng)建對(duì)象:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { ……………… singletonObject = singletonFactory.getObject(); newSingleton = true; ………… if (newSingleton) { //添加到單例緩存中 addSingleton(beanName, singletonObject); } } return singletonObject; } } //由于緩存單例對(duì)象的 hashmap沒(méi)有hellword對(duì)象,進(jìn)入singletonFactory.getObject()方法 , //繼續(xù)斷點(diǎn)到 AbstractAutowireCapableBeanFactory的doCreateBean放法 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //創(chuàng)建bean對(duì)象的包裝器,beanName=hellowordService, //該方法執(zhí)行完成后輸出第一步日志:1->HelloWorldService constructor instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance();//創(chuàng)建bean對(duì)象 ………… try { //從RootBeanDefinition 獲取屬性信息并填充到instanceWrapper對(duì)象 populateBean(beanName, mbd, instanceWrapper); //進(jìn)入初始化bean對(duì)象的操作 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } ………… //將創(chuàng)建好的bean對(duì)象注冊(cè)到緩存起來(lái) registerDisposableBeanIfNecessary(beanName, bean, mbd); } ………… protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 開(kāi)始調(diào)用各種ware接口的方法,會(huì)輸出2、3、4步的日志 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //執(zhí)行BeanPostProcessor的前置方法postProcessBeforeInitialization,由于 //ApplicationContextAwareProcessor實(shí)現(xiàn)該接口,該類(lèi)中會(huì)執(zhí)行很多*Aware的類(lèi),而hellwordService //實(shí)現(xiàn)ApplicationContextAware類(lèi),所在會(huì)輸出:4->ApplicationContextAware.setApplicationContext: wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //init bean對(duì)象 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //執(zhí)行BeanPostProcessor的后置方法postProcessAfterInitialization, wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { //日志輸出 2->BeanNameAware.setBeanName:helloWorldService ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { //日志輸出 3->BeanFactoryAware.setBeanFactory: ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } } ………… protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //日志輸出:5->InitializingBean.afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //執(zhí)行自定義init method方法,輸出日志 :6->init method invokeCustomInitMethod(beanName, bean, mbd); } } } }
最后回到getSingleton方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { …… //添加到單例緩存中 addSingleton(beanName, singletonObject); }
hellwordService對(duì)象創(chuàng)建完畢后,便執(zhí)行 下一步的invokeBeanFactoryPostProcessors方法,輸出第7步日志:
7->BeanFactoryPostProcessor.postProcessBeanFactory 將peopleService的content屬性修改為i am ok
到此為止,invokeBeanFactoryPostProcessors(beanFactory);執(zhí)行完畢
2.3、registerBeanPostProcessors(beanFactory)代碼分析
可以看到代碼和invokeBeanFactoryPostProcessors(beanFactory)的代碼模式幾乎一樣,在本方法中會(huì)創(chuàng)建所有實(shí)現(xiàn)BeanPostProcessor接口類(lèi)并注冊(cè)到beanFactory中供后面對(duì)象創(chuàng)建時(shí)回調(diào),代碼不再做分析
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }
2.4、registerListeners();代碼分析
protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { //hellowordService便在此處注冊(cè) getApplicationEventMulticaster().addApplicationListener(listener); } ………… }
2.5、finishBeanFactoryInitialization(beanFactory)代碼分析
斷點(diǎn)直接進(jìn)入一下代碼:
public void preInstantiateSingletons() throws BeansException { ? ?if (logger.isTraceEnabled()) { ? ? ? logger.trace("Pre-instantiating singletons in " + this); ? ?} ? ?List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); ? ?// Trigger initialization of all non-lazy singleton beans... ? ?for (String beanName : beanNames) { ? ? ? RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); ? ? ? if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { ? ? ? ? ?if (isFactoryBean(beanName)) { ? ? ? ? ? ? Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); ? ? ? ? ? ? if (bean instanceof FactoryBean) { ? ? ? ? ? ? ? ?final FactoryBean<?> factory = (FactoryBean<?>) bean; ? ? ? ? ? ? ? ?boolean isEagerInit; ? ? ? ? ? ? ? ?if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { ? ? ? ? ? ? ? ? ? isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((SmartFactoryBean<?>) factory)::isEagerInit, ? ? ? ? ? ? ? ? ? ? ? ? getAccessControlContext()); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?else { ? ? ? ? ? ? ? ? ? isEagerInit = (factory instanceof SmartFactoryBean && ? ? ? ? ? ? ? ? ? ? ? ? ((SmartFactoryBean<?>) factory).isEagerInit()); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?if (isEagerInit) { ? ? ? ? ? ? ? ? ? getBean(beanName); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? } ? ? ? ? ?} ? ? ? ? ?else { ? ? ? ? ? ? //所有非lazy對(duì)象便在此處創(chuàng)建,如實(shí)例中的peopleServcie,對(duì)象創(chuàng)建過(guò)程前面已分析 ? ? ? ? ? ?//peopleServcie的創(chuàng)建過(guò)程回掉beanpostProcessors的前置和后置方法,輸出日志: ? ? ? ? ? ?//8->BeanPostProcessor.postProcessBeforeInitialization->peopleService ? ? ? ? ? ?//9->BeanPostProcessor.postProcessAfterInitialization->peopleService ? ? ? ? ? ? getBean(beanName); ? ? ? ? ?} ? ? ? } ? ?} ………… }
2.4、finishRefresh()代碼分析
protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). clearResourceCaches(); // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event. //發(fā)布ContextRefreshedEvent事件,輸入日志 //10->ApplicationListener.onApplicationEvent: publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
到此代碼分析完畢,以上只是簡(jiǎn)要的分析了初始化過(guò)程中關(guān)鍵代碼,還有很多細(xì)節(jié)大家可自己斷點(diǎn)跟蹤。
總結(jié)
到此這篇關(guān)于spring初始化源碼代碼淺析的文章就介紹到這了,更多相關(guān)spring初始化源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java編程一維數(shù)組轉(zhuǎn)換成二維數(shù)組實(shí)例代碼
這篇文章主要介紹了Java編程一維數(shù)組轉(zhuǎn)換成二維數(shù)組,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Springboot swagger配置過(guò)程詳解(idea社區(qū)版2023.1.4+apache-maven-3
這篇文章主要介紹了Springboot-swagger配置(idea社區(qū)版2023.1.4+apache-maven-3.9.3-bin),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07springboot:接收date類(lèi)型的參數(shù)方式
這篇文章主要介紹了springboot:接收date類(lèi)型的參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10詳解Spring AOP 實(shí)現(xiàn)主從讀寫(xiě)分離
本篇文章主要介紹了Spring AOP 實(shí)現(xiàn)主從讀寫(xiě)分離,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03java socket長(zhǎng)連接中解決read阻塞的3個(gè)辦法
這篇文章主要介紹了java socket長(zhǎng)連接中解決read阻塞的3個(gè)辦法,本文取了折中的一個(gè)方法,并給出代碼實(shí)例,需要的朋友可以參考下2014-08-08java在linux本地執(zhí)行shell命令的實(shí)現(xiàn)方法
本文主要介紹了java在linux本地執(zhí)行shell命令的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02