溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì)

發(fā)布時(shí)間:2021-10-27 09:24:06 來源:億速云 閱讀:143 作者:柒染 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

1. Spring IoC容器概述

1.1 IoC容器和依賴反轉(zhuǎn)模式

為什么要依賴反轉(zhuǎn)?

在依賴反轉(zhuǎn)時(shí)實(shí)際是依賴對(duì)象的獲得被反轉(zhuǎn)了。
如果合作對(duì)象的引用或依賴關(guān)系的管理由具體對(duì)象來完成,會(huì)導(dǎo)致代碼高耦合和可測(cè)試性降低,而在面向?qū)ο笙到y(tǒng)中,對(duì)象封裝了數(shù)據(jù)和對(duì)數(shù)據(jù)的處理,對(duì)象的依賴關(guān)系常常在于對(duì)數(shù)據(jù)和方法的依賴,因此把對(duì)象的依賴注入交給框架和IoC容器來完成,解耦的同時(shí)可以提高代碼的可測(cè)試性.

Spring中依賴反轉(zhuǎn)的實(shí)現(xiàn)

在Spring中IoC容器是實(shí)現(xiàn)依賴反轉(zhuǎn)的載體,它可以讓對(duì)象在生成或?qū)ο蟪跏蓟瘯r(shí)直接將數(shù)據(jù)注入到對(duì)象中;也可以通過將對(duì)象的引用注入到對(duì)象數(shù)據(jù)域中從而實(shí)現(xiàn)注入對(duì)方法調(diào)用的依賴.這種依賴注入可以遞歸的將對(duì)象逐層注入。

通過使用IoC容器,對(duì)象依賴關(guān)系的管理被反轉(zhuǎn)了,轉(zhuǎn)到IoC容器中來了,對(duì)象之間的相互依賴關(guān)系由IoC容器進(jìn)行管理,并由IoC容器完成對(duì)象的注入。

2. IoC容器系列的設(shè)計(jì)與實(shí)現(xiàn)

2.1 Ioc容器系列 BeanFactory與ApplicationContext

在Spring IoC容器的設(shè)計(jì)中,可以看到二個(gè)主要的容器系列,一個(gè)是實(shí)現(xiàn)BeanFactory接口的簡(jiǎn)單容器系列,這系列容器只實(shí)現(xiàn)了容器的基本功能;
另一個(gè)是ApplicationContext應(yīng)用上下文,作為容器的高級(jí)形態(tài)而存在.它在簡(jiǎn)單容器的基礎(chǔ)上,增加了許多面向框架的特性,對(duì)應(yīng)用環(huán)境進(jìn)作了許多適配.

2.2 Spring IoC容器的設(shè)計(jì)

IoC容器的主要接口設(shè)計(jì)圖如下圖所示:
怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì)

由上圖可以看出IoC容器接口有二條設(shè)計(jì)路線:

  1. 從接口BeanFactory到HierarchicalBeanFactory,再到ConfigableBeanFactory是一條主要的設(shè)計(jì)路線。

  2. 另一條是以ApplicationContext應(yīng)用上下文接口為核心的接口設(shè)計(jì)路線。從BeanFactory到ListableBeanFactory及HierarchicalBeanFactory,再到ApplicationContext,再到常用的WebApplicationContext或ConfigableApplicationContext。

  3. 圖中綠色部分,為部分抽象類及接口實(shí)現(xiàn)類,暫不研究。

對(duì)于第一條接口設(shè)計(jì)路線,BeanFactory定義了基本的容器設(shè)計(jì)規(guī)范,HierarchicalBeanFactory繼承了BeanFactory基本接口之后,增加了getParentBeanFactory()接口功能,使BeanFactory具備了雙親IoC容器的管理功能。而后面的ConfigableBeanFactory主要定義了一些BeanFactory的配置功能(如通過setParentBeanFacory()設(shè)置雙親IoC容器等)。通過這些功能的疊加就定義了BeanFactory簡(jiǎn)單IoC容器的基本功能。

對(duì)于第二條接口設(shè)計(jì)路線,ListableBeanFactory及HierarchicalBeanFactory是連接BeanFactory及ApplicationContext的接口;在ListableBeanFactory接口中細(xì)化了許多BeanFactory接口的功能,在HierarchicalBeanFactory接口中增加了getParentBeanFactory()接口功能,使BeanFactory具備了雙親IoC容器的管理功能;對(duì)于ApplicationContext接口,通過繼承ResourcePatternResolver,ApplicationEventPublisher,MessageSource等接口,在BeanFactory簡(jiǎn)單容器的基礎(chǔ)上增加了許多對(duì)高級(jí)容器特性的支持。

2.3 BeanFactory接口

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";	//如果以&開始則獲取FactoryBean本身;否則獲取FactoryBean創(chuàng)建的實(shí)例.
	//獲取Bean
	Object getBean(String name) throws BeansException;//可以是別名
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	//判斷是否包含bean。不管是抽象類,懶加載,是否在容器范圍內(nèi),只要符合都返回true。所以返回true時(shí),不一定能從getBean獲取實(shí)例
	boolean containsBean(String name);
	//單例,原型,bean類型的判斷
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
//獲取bean 的類型,別名
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	String[] getAliases(String name);
}

2.4 BeanFactory容器的設(shè)計(jì)原理

以XmlBeanFactory為例,來說明簡(jiǎn)單IoC容器BeanFactory的設(shè)計(jì)原理。

2.4.1 XmlBeanFactory類繼承關(guān)系

怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì)

可以看出XmlBeanFactory繼承自DefaultListableBeanFactory,在Spring中實(shí)際上是把DefaultListableBeanFactory作為一個(gè)功能完整的IoC容器來使用的。

2.4.2 XmlBeanFactory的實(shí)現(xiàn)

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader.loadBeanDefinitions(resource);
    }
}
  • 從XmlBeanFactory的名字上可以看出,它是一個(gè)可以讀取以XML文件方式定義的BeanDefinition的IoC容器。

  • 在XmlBeanFactory中初始化了一個(gè)XmlBeanDefinitionReader對(duì)象,用來處理以XML文件方式定義的BeanDefinition。

  • 構(gòu)造XmlBeanFactory這個(gè)IoC容器時(shí)需要指定XML信息來源,這個(gè)信息來源需要封裝成Spring的Resource類。

通過xml文件位置構(gòu)造出Resource,然后將Resource傳入XmlBeanFactory的構(gòu)造函數(shù)。這樣IoC容器就可以定位到需要的BeanDefinition信息來完成容器的初始化和依賴注入過程。

2.4.3 總結(jié)IoC容器的使用步驟

參考XmlBeanFactory的實(shí)現(xiàn),我們以編程的方式使用DefaultListableBeanFactory來進(jìn)行總結(jié)。

	public void mytest(){
		ClassPathResource resource = new ClassPathResource("applicationContext.xml");
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory);
		System.out.println(beanDefinitionReader.loadBeanDefinitions(resource));
		Person p = (Person) factory.getBean("personChild");
		System.out.println(p);
	}

發(fā)現(xiàn)再使用 IoC容器時(shí)需要以下幾個(gè)步驟:

  1. 創(chuàng)建IoC容器的抽象資源,這個(gè)抽象資源定義了BeanDefinition的定義信息。

  2. 創(chuàng)建一個(gè)BeanFactory。這里是DefaultListableBeanFactory。

  3. 創(chuàng)建一個(gè)BeanDefinition的讀取器,通過一個(gè)回調(diào)配置給BeanFactory。這里是XmlBeanDefinitionReader。

  4. 從定義好的資源位置讀入配置信息,具體的解析過程由XmlBeanDefinitionReader來完成。完成整個(gè)載入和注冊(cè)Bean定義后,就可以使用IoC容器了。

2.5 ApplicationContext接口

ApplicationContext的接口關(guān)系:如下圖所示。

怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì)

可以看出ApplicationContext在BeanFactory的基礎(chǔ)上增加了許多附加功能,為ApplicationContext提供了許多新特新,所以說,ApplicationContext在BeanFactory是一個(gè)高級(jí)形態(tài)意義的IoC容器。

2.6 ApplicationContext容器的設(shè)計(jì)原理

在ApplicationContext在BeanFactory容器中,以FileSystemXMLApplicationContext實(shí)現(xiàn)為例來說明ApplicationContext在BeanFactory容器的設(shè)計(jì)原理。
FileSystemXMLApplicationContext的源代碼如下:

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {

	public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
		super(parent);
		setConfigLocations(configLocations);
		//這個(gè)refresh操作會(huì)牽涉IoC容器啟動(dòng)的一系列操作。對(duì)不同的容器操作都是類似的,因此在基類中將他們封裝好。
		if (refresh) {
			refresh();
		}
	}
	@Override
	protected Resource getResourceByPath(String path) {
		if (path != null && path.startsWith("/")) {
			path = path.substring(1);
		}
		return new FileSystemResource(path);
	}
}

由代碼可以看出主要功能已經(jīng)在基類AbstractXmlApplicationContext中實(shí)現(xiàn)了,在FileSystemXmlApplicationContext中只需要二個(gè)與自身設(shè)計(jì)有關(guān)的功能。

功能一

應(yīng)用直接使用FileSystemXmlApplicationContext容器時(shí),對(duì)于實(shí)例化這個(gè)應(yīng)用上下文的支持,及啟動(dòng)IoC容器的refresh功能。

功能二

不同的容器實(shí)現(xiàn)對(duì)應(yīng)著不同BeanDefinition讀取實(shí)現(xiàn),在FileSystemXmlApplicationContext的讀取BeanDefinition實(shí)現(xiàn)如上面的代碼所示。

關(guān)于怎樣進(jìn)行Spring中IOC容器的概述與設(shè)計(jì)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI