日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
給學(xué)妹看的SpringIOC面試題(上)

前段時(shí)間是校招的高峰期啊,很多學(xué)弟,學(xué)妹們出去面試的時(shí)候都會(huì)被問(wèn)到一個(gè)問(wèn)題,談?wù)勀銓?duì)Spring的理解?

創(chuàng)新互聯(lián)建站從2013年開始,先為崇禮等服務(wù)建站,崇禮等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為崇禮企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

很多同學(xué)都是會(huì)說(shuō)一些IOC,AOP等,但是聊到一些細(xì)節(jié)IOC里面的細(xì)節(jié)點(diǎn),就不知怎么接著和面試官怎么聊了。

所以今天我就跟大家具體詳細(xì)聊聊SpringIOC 那些事!!!

什么是Spring

spring 首先它是一個(gè)框架,在我們的開發(fā)工作的環(huán)境中,所有的其他的框架基本都依賴Spring,spring起著一個(gè)容器的作用,用來(lái)承載我們整體的bean對(duì)象。它幫我們整理了整個(gè)bean的從創(chuàng)建到銷毀的管理。

IOC控制反轉(zhuǎn)是啥?

類的創(chuàng)建、銷毀都由 Spring 來(lái)控制,也就是說(shuō)控制對(duì)象生存周期的不再是引用它的對(duì)象,而是 Spring來(lái)控制整個(gè)過(guò)程。對(duì)于某個(gè)具體的對(duì)象而言,以前是它控制其他對(duì)象,現(xiàn)在是所有對(duì)象都被 Spring 控制。

看到這里其實(shí)這都是一些簡(jiǎn)單的理解,以及一些官方的說(shuō)法,為了真正的搞懂什么是SpringIoc,就上面的這些東西是遠(yuǎn)遠(yuǎn)不夠的,所以我給大家畫了一個(gè)流程圖,跟著這個(gè)流程圖,我們一步一步來(lái)解析IOC。

只有解析完了流程,我們才能有一個(gè)整體的架構(gòu)的脈絡(luò)思路,后面我們?cè)倭腄I(依賴注入)以及怎么處理的緩存依賴。

這里跟大家分享一個(gè)知識(shí)點(diǎn),在看一些架構(gòu)的源碼的時(shí)候,大家一定要先理清整體架構(gòu)的脈絡(luò),這樣才能方便我們理解整個(gè)架構(gòu),否則就是一面茫然,不知道寫的是啥!!!

話不多說(shuō)了,還是直接來(lái)看下這個(gè)整體流程圖!!!

從這個(gè)圖,我們還是從上到下,從左到右的順序來(lái)講解哈。

 
 
 
 
  1. public static void main(String[] args) {
  2.     ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
  3. }

我們以開始啟動(dòng)spring容器開始,常見配置bean有 XML 配置文件的形式或者注解形式等還有一些其他的方式。

不管哪種方式,spring考慮到擴(kuò)展性問(wèn)題,會(huì)通過(guò)BeanDefinitionReader,來(lái)加載bean的配置信息,然后生成一個(gè)BeanDefinition(bean的定義信息,用來(lái)存儲(chǔ) bean 的所有屬性方法定義)。

BeanDefinitionReader 只是接口約束一些定義信息,常見的實(shí)現(xiàn)類 XmlBeanDefinitionReader(xml形式),PropertiesBeanDefinitionReader(Properties配置文件),AbstractBeanDefinitionReader (相關(guān)一些環(huán)境信息)等。

BeanFactoryPostProcesser

說(shuō)完了BeanDefinition那么接下來(lái)就是走到BeanFactoryPostProcessor。

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時(shí)對(duì)外暴露的擴(kuò)展點(diǎn),其實(shí)就是在bean的實(shí)例化之前,可以獲取bean的定義信息,以及修改相關(guān)信息。

比如說(shuō)我們現(xiàn)在常見的注解方式來(lái)加載bean信息,里面其實(shí)就是也是用的BeanFactoryPostProcessor的子類實(shí)現(xiàn)的。

我們常見的 @Service、@Controller、@Repository等注解其實(shí)都是組合注解,里面里面都是包含Component注解實(shí)現(xiàn)的,如下GIF動(dòng)圖所示:

ps:太大了加載可能會(huì)出問(wèn)題。

從這個(gè)動(dòng)圖中大家可以發(fā)現(xiàn)BeanFactoryPostProcessor有一堆的實(shí)現(xiàn)子類,因此當(dāng)我們有自己的業(yè)務(wù)邏輯實(shí)現(xiàn)的時(shí)候也只需要實(shí)現(xiàn)BeanFactoryPostProcessor就可以了,然后加上@Component注解就可以了。

BeanFactory

BeanFactory,從名字上也很好理解,生產(chǎn) bean 的工廠,它負(fù)責(zé)生產(chǎn)和管理各個(gè) bean 實(shí)例。同時(shí)也是Spring容器暴露在外獲取bean的入口

BeanFactory的生產(chǎn)過(guò)程其實(shí)是利用反射機(jī)制實(shí)現(xiàn)的。

接下來(lái)我們?cè)賮?lái)看一下BeanFactory的繼承關(guān)系。

這張關(guān)系圖我們只要了解的幾個(gè)關(guān)鍵點(diǎn):

  • HierarchicalBeanFactory:提供父容器的訪問(wèn)功能
  • ListableBeanFactory:提供了批量獲取Bean的方法
  • AutowireCapableBeanFactory:在BeanFactory基礎(chǔ)上實(shí)現(xiàn)對(duì)已存在實(shí)例的管理
  • ConfigurableBeanFactory:?jiǎn)卫齜ean的注冊(cè)以及生成實(shí)例,統(tǒng)計(jì)單例bean等信息
  • ConfigurableListableBeanFactory:增加了一些其他功能:類加載器、類型轉(zhuǎn)化、屬性編輯器、BeanPostProcessor、bean定義、處理bean依賴關(guān)系、 bean如何銷毀等等一些還有其他的功能
  • DefaultListableBeanFactory:實(shí)現(xiàn)BeanFactory所有功能同時(shí)也能注冊(cè)BeanDefinition

可能有人要問(wèn)了,ApplicationContext和BeanFactory是不是只是繼承關(guān)系?

 
 
 
 
  1. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
  2.        BeanFactory factory = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 

BeanFactory是一個(gè)底層的IOC容器,而ApplicationContext是在其基礎(chǔ)上增加了一些它的特性的同時(shí)同時(shí)增加了一些其他的整合特性比如:更好的整合SpringAOP、國(guó)際化消息、以及事務(wù)的發(fā)布、資源訪問(wèn)等這些新的特性。

所以BeanFactory和ApplicationContext不是同一個(gè)東西,是兩個(gè)不同的對(duì)象,想要獲取BeanFactory可以通過(guò)applicationContext.getParentBeanFactory()獲取。

所以當(dāng)通過(guò)XML來(lái)配置bean的信息的時(shí)候我們就可以使用BeanFactory作為容器,因?yàn)槲覀儾恍枰心敲炊嗥渌念~外的一些特性。當(dāng)我們通過(guò)注解的形式來(lái)注冊(cè)bean信息的時(shí)候,我們就可以使用ApplicationContext來(lái)作為容器。當(dāng)然這個(gè)只是作為了解,在我們的業(yè)務(wù)代碼中基本是可以不用關(guān)心這一點(diǎn)的。

Bean的生命周期

Spring Bean的生命周期在spring的面試題中這其實(shí)是非常常見的一道面試題,其實(shí)并不用去背那么多流程,在Spring的源碼中其實(shí)已經(jīng)寫好了bean的完整生命流程,上面的BeanFactory中已經(jīng)表明。

  • BeanNameAware#setBeanName:在創(chuàng)建此bean的bean工廠中設(shè)置bean的名稱,在普通屬性設(shè)置之后調(diào)用,在InitializinngBean.afterPropertiesSet()方法之前調(diào)用
  • BeanClassLoaderAware#setBeanClassLoader:將 bean ClassLoaderr 提供給 bean 實(shí)例的回調(diào)
  • BeanFactoryAware#setBeanFactory:回調(diào)提供了自己的bean實(shí)例工廠,在普通屬性設(shè)置之后,在InitializingBean.afterPropertiesSet()或者自定義初始化方法之前調(diào)用
  • org.springframework.context.ResourceLoaderAware#setResourceLoader:在普通bean對(duì)象之后調(diào)用,在afterPropertiesSet 或者自定義的init-method 之前調(diào)用,在 ApplicationContextAware 之前調(diào)用。
  • org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher:在普通bean屬性之后調(diào)用,在初始化調(diào)用afterPropertiesSet 或者自定義初始化方法之前調(diào)用。在 ApplicationContextAware 之前調(diào)用。
  • org.springframework.context.MessageSourceAware#setMessageSource:在普通bean屬性之后調(diào)用,在初始化調(diào)用afterPropertiesSet 或者自定義初始化方法之前調(diào)用,在 ApplicationContextAware 之前調(diào)用。
  • org.springframework.context.ApplicationContextAware#setApplicationContext:在普通Bean對(duì)象生成之后調(diào)用,在InitializingBean.afterPropertiesSet之前調(diào)用或者用戶自定義初始化方法之前。在ResourceLoaderAware.setResourceLoader,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之后調(diào)用
  • org.springframework.web.context.ServletContextAware#setServletContext:運(yùn)行時(shí)設(shè)置ServletContext,在普通bean初始化后調(diào)用
  • org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization:將此BeanPostProcessor 應(yīng)用于給定的新bean實(shí)例
  • InitializingBean#afterPropertiesSet:在設(shè)置所有 bean 屬性后由包含的 BeanFactory調(diào)用
  • org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName:獲取InitMethodName名稱,并且運(yùn)行初始化方法
  • org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
  • DisposableBean#destroy:銷毀
  • org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName:返回被銷毀的bean名稱

這其實(shí)就是bean的整個(gè)生命周期過(guò)程,其實(shí)這里面注視大家都是可以自己查看的,每一個(gè)方法上面都是很詳細(xì)注釋,我也只是根據(jù)注視簡(jiǎn)單的翻譯了一下。

整個(gè)過(guò)程bean的生命周期可以縮短理解為:

但是要完全理解Spring,那肯定就要說(shuō)Spring里面的一個(gè)非常重要的方法 **ApplicationContext.refresh()**這其中的包含了13個(gè)子方法:

 
 
 
 
  1. public void refresh() throws BeansException, IllegalStateException {
  2.    //   添加一個(gè)synchronized 防止出現(xiàn)refresh還沒(méi)有完成出現(xiàn)其他的操作(啟動(dòng),或者銷毀) 
  3.    synchronized (this.startupShutdownMonitor) {
  4.       // 1.準(zhǔn)備工作
  5.       // 記錄下容器的啟動(dòng)時(shí)間、
  6.       // 標(biāo)記“已啟動(dòng)”狀態(tài),關(guān)閉狀態(tài)為false、
  7.       // 加載當(dāng)前系統(tǒng)屬性到環(huán)境對(duì)象中
  8.       // 準(zhǔn)備一系列監(jiān)聽器以及事件集合對(duì)象
  9.        prepareRefresh();
  10.       // 2. 創(chuàng)建容器對(duì)象:DefaultListableBeanFactory,加載XML配置文件的屬性到當(dāng)前的工廠中(默認(rèn)用命名空間來(lái)解析),就是上面說(shuō)的BeanDefinition(bean的定義信息)這里還沒(méi)有初始化,只是配置信息都提取出來(lái)了,(包含里面的value值其實(shí)都只是占位符)
  11.       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  12.       // 3. BeanFactory的準(zhǔn)備工作,設(shè)置BeanFactory的類加載器,添加幾個(gè)BeanPostProcessor,手動(dòng)注冊(cè)幾個(gè)特殊的bean等
  13.       prepareBeanFactory(beanFactory);
  14.       try {
  15.          // 4.子類的覆蓋方法做額外的處理,就是我們剛開始說(shuō)的 BeanFactoryPostProcessor ,具體的子類可以在這步的時(shí)候添加一些特殊的BeanFactoryPostProcessor完成對(duì)beanFactory修改或者擴(kuò)展。
  16.          // 到這里的時(shí)候,所有的Bean都加載、注冊(cè)完成了,但是都還沒(méi)有初始化
  17.          postProcessBeanFactory(beanFactory);
  18.          // 5.調(diào)用 BeanFactoryPostProcessor 各個(gè)實(shí)現(xiàn)類的 postProcessBeanFactory(factory) 方法
  19.          invokeBeanFactoryPostProcessors(beanFactory);
  20.          // 6.注冊(cè) BeanPostProcessor  處理器 這里只是注冊(cè)功能,真正的調(diào)用的是getBean方法
  21.         registerBeanPostProcessors(beanFactory);
  22.          // 7.初始化當(dāng)前 ApplicationContext 的 MessageSource,即國(guó)際化處理
  23.          initMessageSource();
  24.          // 8.初始化當(dāng)前 ApplicationContext 的事件廣播器,
  25.          initApplicationEventMulticaster();
  26.          // 9.從方法名就可以知道,典型的模板方法(鉤子方法),感興趣的同學(xué)還可以再去復(fù)習(xí)一下之前寫的設(shè)計(jì)模式中的-模版方法模式
  27.          //  具體的子類可以在這里初始化一些特殊的Bean(在初始化 singleton beans 之前)
  28.          onRefresh();
  29.          // 10.注冊(cè)事件監(jiān)聽器,監(jiān)聽器需要實(shí)現(xiàn) ApplicationListener 接口。這也不是我們的重點(diǎn),過(guò)
  30.          registerListeners();
  31.          // 11.初始化所有的 singleton beans(lazy-init 的除外),重點(diǎn)關(guān)注
  32.          finishBeanFactoryInitialization(beanFactory);
  33.          // 12.廣播事件,ApplicationContext 初始化完成
  34.          finishRefresh();
  35.       }
  36.       catch (BeansException ex) {
  37.          if (logger.isWarnEnabled()) {
  38.             logger.warn("Exception encountered during context initialization - " +
  39.                   "cancelling refresh attempt: " + ex);
  40.          }
  41.          // 13.銷毀已經(jīng)初始化的 singleton 的 Beans,以免有些 bean 會(huì)一直占用資源
  42.          destroyBeans();
  43.         
  44.          cancelRefresh(ex);
  45.          // 把異常往外拋
  46.          throw ex;
  47.       }
  48.       finally {
  49.          // Reset common introspection caches in Spring's core, since we
  50.          // might not ever need metadata for singleton beans anymore...
  51.          resetCommonCaches();
  52.       }
  53.    }
  54. }

這里只是大致的說(shuō)明一下這里的每個(gè)方法的用途,如果還想要了解的更深,就需要大家自己再去看這里面的更深成次的代碼了,這個(gè)大家可以自己嘗試的斷點(diǎn)試一下。或者后面再單獨(dú)給大家寫一篇這里面的細(xì)節(jié)流程。

斷點(diǎn)看源碼不必要每個(gè)方法都去看,先了解一個(gè)大概,然后再多斷點(diǎn)幾次,每次斷點(diǎn)都相對(duì)上一次進(jìn)入的更深成次一點(diǎn),滿滿的你就能全部理解了。這是一個(gè)漫長(zhǎng)的過(guò)程。

總結(jié)

Spring IOC整個(gè)啟動(dòng)過(guò)程我們就先講到這里,由于篇幅問(wèn)題一下子寫的太長(zhǎng)怕看起來(lái)有點(diǎn)難受,后面再接著跟大家分享怎么處理循環(huán)依賴問(wèn)題,以及DI依賴注入等源碼分析

看到這里給大家整理了幾個(gè)比較常見的面試來(lái)加深一下鞏固:

BeanFactory和ApplicationContext的區(qū)別?

BeanFactory是一個(gè)底層的IOC容器,而ApplicationContext是在其基礎(chǔ)上增加了一些它的特性的同時(shí)同時(shí)增加了一些其他的整合特性比如:更好的整合SpringAOP、國(guó)際化消息、以及事務(wù)的發(fā)布、資源訪問(wèn)等這些新的特性

BeanFactory 與 FactoryBean的區(qū)別?

BeanFactory 是 IoC 底層容器 ,FactoryBean 是 創(chuàng)建 Bean 的一種方式,幫助實(shí)現(xiàn)復(fù)雜的初始化邏輯

Spring IoC 容器的啟動(dòng)過(guò)程?

這個(gè)問(wèn)題只要看懂了第一張流程圖,以及最后的ApplicationContext.refresh()方法中的內(nèi)部13個(gè)子方法,再回答這個(gè)問(wèn)題應(yīng)該問(wèn)題不大,面試官應(yīng)該會(huì)眼前一亮,ho,有點(diǎn)東西!!!


當(dāng)前題目:給學(xué)妹看的SpringIOC面試題(上)
文章分享:http://m.5511xx.com/article/coisees.html