多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php框架 > 框架設計 > 【初探Spring】——Spring IOC(三):初始化過程—Resource定位

【初探Spring】——Spring IOC(三):初始化過程—Resource定位

來源:程序員人生   發布時間:2016-07-19 13:07:59 閱讀次數:3672次

我們知道Spring的IoC起到了1個容器的作用,其中裝得都是各種各樣的Bean。同時在我們剛剛開始學習Spring的時候都是通過xml文件來定義Bean,Spring會某種方式加載這些xml文件,然后根據這些信息綁定全部系統的對象,終究組裝成1個可用的基于輕量級容器的利用系統。

Spring IoC容器整體可以劃分為兩個階段,容器啟動階段,Bean實例化階段。其中容器啟動階段蛀牙包括加載配置信息、解析配置信息,設備到BeanDefinition中和其他后置處理,而Bean實例化階段主要包括實例化對象,裝配依賴,生命周期管理已注冊回調。下面LZ先介紹容器的啟動階段的第1步,即定位配置文件。

我們使用編程方式使用DefaultListableBeanFactory時,首先是需要定義1個Resource來定位容器使用的BeanDefinition。

ClassPathResource resource = new ClassPathResource("bean.xml");

通過這個代碼,就意味著Spring會在類路徑中去尋覓bean.xml并解析為BeanDefinition信息。固然這個Resource其實不能直接被使用,他需要被BeanDefinitionReader進行解析處理(這是后面的內容了)。

對各種applicationContext,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等等,我們從這些類名就能夠看到他們提供了那些Resource的讀入功能。下面我們以FileSystemXmlApplicationContext為例來論述Spring IoC容器的Resource定位。

先看FileSystemXmlApplicationContext繼承體系結構:


從圖中可以看出FileSystemXMLApplicationContext繼承了DefaultResourceLoader,具有了Resource定義的BeanDefinition的能力,其源代碼以下:

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { /** * 默許構造函數 */ public FileSystemXmlApplicationContext() { } public FileSystemXmlApplicationContext(ApplicationContext parent) { super(parent); } public FileSystemXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } public FileSystemXmlApplicationContext(String... configLocations) throws BeansException { this(configLocations, true, null); } public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException { this(configLocations, true, parent); } public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException { this(configLocations, refresh, null); } //核心構造器 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } //通過構造1個FileSystemResource對象來得到1個在文件系統中定位的BeanDefinition //采取模板方法設計模式,具體的實現用子類來完成 protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); } }

AbstractApplicationContext中的refresh()方法是IoC容器初始化的入口,也就是說IoC容器的初始化是通過refresh()方法來完成全部調用進程的。在核心構造器中就對refresh進行調用,通過它來啟動IoC容器的初始化工作。getResourceByPath為1個模板方法,通過構造1個FileSystemResource對象來得到1個在文件系統中定位的BeanDEfinition。getResourceByPath的調用關系以下(部份):


refresh為初始化IoC容器的入口,但是具體的資源定位還是在XmlBeanDefinitionReader讀入BeanDefinition時完成,loadBeanDefinitions() 加載BeanDefinition的載入。

protected final void refreshBeanFactory() throws BeansException { //判斷是不是已創建了BeanFactory,如果創建了則燒毀關閉該BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //創建DefaultListableBeanFactory實例對象 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //加載BeanDefinition信息 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

DefaultListableBeanFactory作為BeanFactory默許實現類,其重要性不言而喻,而createBeanFactory()則返回該實例對象。

protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }

loadBeanDefinition方法加載BeanDefinition信息,BeanDefinition就是在這里定義的。AbstractRefreshableApplicationContext對loadBeanDefinitions僅僅只是定義了1個抽象的方法,真實的實現類為其子類AbstractXmlApplicationContext來實現:

AbstractRefreshableApplicationContext:

protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException;

AbstractXmlApplicationContext:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //創建bean的讀取器(Reader),即XmlBeanDefinitionReader,并通過回調設置到容器中 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // beanDefinitionReader.setEnvironment(getEnvironment()); //為Bean讀取器設置Spring資源加載器 beanDefinitionReader.setResourceLoader(this); //為Bean讀取器設置SAX xml解析器 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // initBeanDefinitionReader(beanDefinitionReader); //Bean讀取器真正實現的地方 loadBeanDefinitions(beanDefinitionReader); }

程序首先首先創建1個Reader,在前面就提到過,每類資源都對應著1個BeanDefinitionReader,BeanDefinitionReader提供統1的轉換規則;然后設置Reader,最后調用loadBeanDefinition,該loadBeanDefinition才是讀取器真正實現的地方:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //獲得Bean定義資源的定位 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } //獲得Bean定義資源的路徑。在FileSystemXMLApplicationContext中通過setConfigLocations可以配置Bean資源定位的路徑 String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }

首先通過getConfigResources()獲得Bean定義的資源定位,如果不為null則調用loadBeanDefinitions方法來讀取Bean定義資源的定位。

loadBeanDefinitions是中的方法:

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int counter = 0; for (String location : locations) { counter += loadBeanDefinitions(location); } return counter; }

繼續:

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { return loadBeanDefinitions(location, null); }

再繼續:

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { //獲得ResourceLoader資源加載器 ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } // if (resourceLoader instanceof ResourcePatternResolver) { try { //調用DefaultResourceLoader的getResourceByPath完成具體的Resource定位 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); } return loadCount; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { //調用DefaultResourceLoader的getResourceByPath完成具體的Resource定位 Resource resource = resourceLoader.getResource(location); int loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } }

在這段源代碼中通過調用DefaultResourceLoader的getResource方法:

public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); if (location.startsWith("/")) { return getResourceByPath(location); } //處理帶有classPath標識的Resource else if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { //處理URL資源 URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException ex) { return getResourceByPath(location); } } }

在getResource方法中我們可以清晰地看到Resource資源的定位。這里可以清晰地看到getResourceByPath方法的調用,getResourceByPath方法的具體實現有子類來完成,在FileSystemXmlApplicationContext實現以下:

protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }

這樣代碼就回到了博客開初的FileSystemXmlApplicationContext 中來了,它提供了FileSystemResource 來完成從文件系統得到配置文件的資源定義。固然這僅僅只是Spring IoC容器定位資源的1種邏輯,我們可以根據這個步驟來查看Spring提供的各種資源的定位,如ClassPathResource、URLResource等等。下圖是ResourceLoader的繼承關系:

這里就差不多分析了Spring IoC容器初始化進程資源的定位,在BeanDefinition定位完成的基礎上,就能夠通過返回的Resource對象來進行BeanDefinition的載入、解析了。

下篇博客將探索Spring IoC容器初始化進程的解析,Spring Resource體系結構會在后面詳細講授。

 

參考文獻

1、《Spring技術內幕 深入解析Spring架構與設計原理》–第2版

2、Spring:源碼解讀Spring IOC原理

3、【Spring】IOC核心源碼學習(2):容器初始化進程

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 一级特黄特黄毛片欧美的 | 免费不卡毛片 | 亚洲美女又黄又爽在线观看 | 亚洲成人在线视频 | 白嫩美女一级毛片免费看 | 国产一区二区日韩欧美在线 | 亚洲国产精品综合一区在线 | 全国男人的天堂网站 | 最近免费字幕中文大全在线观看 | 一级做a爰片久久毛片 | 日韩亚洲欧美性感视频影片免费看 | 成人三级精品视频在线观看 | 欧美video粗暴变态 | 黄上床大片| www.国产精品视频 | 国产精品国产三级在线高清观看 | 国产成人免费a在线资源 | 午夜在线网站 | 亚洲国产成人99精品激情在线 | 中文字幕一二三区乱码老 | 美国一级毛片视频 | 91探花国产综合在线精品 | 欧美操美女 | 爱爱的免费视频 | 亚洲国产一区二区三区综合片 | 日韩 视频在线播放 | 亚洲图欧美 | 最近在线更新中文字幕3 | 在线碰碰视频在线观看 | 性欧美video另类hd | 日本肥老太成熟 | 欧美一区二区三区视视频 | 久久大香伊人中文字幕 | 成人午夜在线视频 | 国产1区精品 | 欧美偷| 性欧美17一18sex性高清 | 精品国产精品a | 欧美一级做一a做片性视频 欧美一级做一级爱a做片性 | 尤物精品 | 外国美女一级片 |