1. 程式人生 > >Spring原始碼閱讀-IOC 容器解析

Spring原始碼閱讀-IOC 容器解析

在Spring框架中最重要的是Spring IoC容器,它是Spring框架的核心。本文將從更高的角度來解析Sping IoC容器,瞭解其是如何設計的。瞭解一樣東西最好的辦法是從其核心本質出發,只要把握住了這樣一個核心,其他的一些東西也迎刃而解了。這是一個很好的開端,我們一起開始吧...

Spring IoC容器

org.springframework.context.ApplicationContext介面代表Spring IoC容器,主要負責bean的例項化、配置、裝配,簡而言之,Spring IoC容器是管理這些bean的(這裡所說的bean指的是組成你的應用程式中的物件,並且這些物件被Spring所管理)。容器如何知道哪些物件要進行例項化、配置和裝配的呢?是通過讀取配置檔案元資料來達到這個效果的,配置檔案元資料是用xml配置、Java註解和Java程式碼配置來表示的。這使得作為程式設計師的我們,只需要向Spring容器提供配置元資料,Spring容器就能在我們的應用中例項化、配置和裝配這些物件。org.springframework.beans和org.springframework.context包是Spring IoC容器的基礎。Spring提供了很多Application介面的實現。在單獨的應用中,建立ClassPathXmlApplicationContext和FileSystemXmlApplicationContext的例項是非常常用的做法。示例如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); Hello hello = (Hello) ac.getBean("hello"); hello.sayHello();

然而在大部分的應用場景中,不需要例項化一個或者多個Spring IoC容器的例項。例如在web應用的場景下,只需要在web.xml中建立七行樣板配置的程式碼如下:

<pre class="xml" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</paramvalue> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>

下面這張圖從更高的視角展示了Spring是怎樣工作的。你的應用程式中的類是和配置元資料組合在一起,以便在ApplicationContext建立和初始化之後,你擁有了一個完全配置的、可執行的系統。

image

ApplicationContext設計解析

為了方便對ApplicationContext介面的層次結構有一個大概的認識,下面使用IDEA來生成ApplicationContext的繼承關係圖。(選中ApplicationContext介面->右鍵->Diagrams->Show Diagrams...)

(溫馨提示:點選圖片可以檢視高清大圖)

image

從上圖就能很清楚的看出ApplicationContext繼承的介面分為五類:

BeanFactory:提供了能夠管理任何物件的高階配置機制,這個介面是Spring框架中比較重要的一個介面。

ListableBeanFactory:從該介面的名字就能知道,該介面除了擁有BeanFactory的功能外,該介面還有能列出factory中所有bean的例項的能力。

HierarchicalBeanFactory:該介面除了擁有BeanFactory的功能外,還提供了BeanFactory分層的機制,查詢bean的時候,除了在自身BeanFactory查詢外,如果沒有查詢到,還會在父級BeanFactory進行查詢。

MessageSource:訊息資源的處理,用於國際化。

ApplicationEventPublisher:用於處理事件釋出機制。

EnvironmentCapable:提供了Environment的訪問能力。

ResourceLoader:用於載入資源的策略介面(例如類路徑下的資源、系統檔案下的資源等等)。

ResourcePatternResolver:用於將位置模式(例如Ant風格的路徑模式)解析成資源物件的策略介面。classpath*:字首能匹配所以類路徑下的資源。

先看一下在ApplicationContext中定義的方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

`String getId(); // 獲取ApplicationContext的唯一id

String getApplicationName(); // 該上下文所屬的已經部署了的應用的名字,預設為""

String getDisplayName(); // 友好的展示名字

long getStartupDate(); // 該上下文第一次載入的時間

ApplicationContext getParent(); // 父級ApplicationContext

AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;`

前四個方法用於獲取該ApplicationContext的一些基本資訊,getAutowireCapableBeanFactory()用於暴露AutowireCapableBeanFactory的功能,這通常不是提供給用於程式碼使用的,除非你想要在應用上下文的外面初始化bean的例項,關於AutowireCapableBeanFactory後面會有更加詳細的解析。

BeanFactory

BeanFactory是Spring框架中比較重要的一個介面,下面列出了這個介面中的方法的定義:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

`// 獲取bean

Object getBean(String name) throws BeansException;

T getBean(String name, Class requiredType) throws BeansException;

Object getBean(String name, Object... args) throws BeansException;

T getBean(Class requiredType) throws BeansException;

T getBean(Class requiredType, Object... args) throws BeansException;

// 獲取bean的提供者(物件工廠)

ObjectProvider getBeanProvider(Class requiredType);

ObjectProvider getBeanProvider(ResolvableType requiredType);

boolean containsBean(String name); // 是否包含指定名字的bean

boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 是否為單例

boolean isPrototype(String name) throws NoSuchBeanDefinitionException; // 是否為原型

// 指定名字的bean是否和指定的型別匹配

boolean isTypeMatch(String name, ResolvableType typeToMatch);

boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;

Class getType(String name)

throws NoSuchBeanDefinitionException; // 獲取指定名字的bean的型別

String[] getAliases(String name); // 獲取指定名字的bean的所有別名`

這些方法大致可以分為三類:

getBean()方法用於獲取匹配的bean的例項物件(有可能是Singleton或者Prototype的),如果沒有找到匹配的bean則丟擲BeansException子類的異常。如果在當前的工廠例項中沒有找到匹配的bean,會在父級的工廠中進行查詢。帶有args引數的getBean()方法,允許顯式的去指定構造器或者工廠方法的引數,會覆蓋了在bean的定義中定義的引數,這僅僅在建立一個新的例項的時候才起作用,而在獲取一個已經存在的例項是不起作用的。

getBeanProvider()方法用於獲取指定bean的提供者,可以看到它返回的是一個ObjectProvider,其父級介面是ObjectFactory。首先來看一下ObjectFactory,它是一個物件的例項工廠,只有一個方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important;">

Copy

T getObject() throws BeansException;

呼叫這個方法返回的是一個物件的例項。此介面通常用於封裝一個泛型工廠,在每次呼叫的時候返回一些目標物件新的例項。ObjectFactory和FactoryBean是類似的,只不過FactoryBean通常被定義為BeanFactory中的服務提供者(SPI)例項,而ObjectFactory通常是以API的形式提供給其他的bean。簡單的來說,ObjectFactory一般是提供給開發者使用的,FactoryBean一般是提供給BeanFactory使用的。

ObjectProvider繼承ObjectFactory,特為注入點而設計,允許可選擇性的程式設計和寬泛的非唯一性的處理。在Spring 5.1的時候,該介面從Iterable擴充套件,提供了對Stream的支援。該介面的方法如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important;">

Copy

`// 獲取物件的例項,允許根據顯式的指定構造器的引數去構造物件

T getObject(Object... args) throws BeansException;

// 獲取物件的例項,如果不可用,則返回null

T getIfAvailable() throws BeansException;

T getIfAvailable(Supplier defaultSupplier) throws BeansException;

void ifAvailable(Consumer dependencyConsumer) throws BeansException;

// 獲取物件的例項,如果不是唯一的或者沒有首先的bean,則返回null

T getIfUnique() throws BeansException;

T getIfUnique(Supplier defaultSupplier) throws BeansException;

void ifUnique(Consumer dependencyConsumer) throws BeansException;

// 獲取多個物件的例項

Iterator iterator();

Stream stream();

Stream orderedStream()`

這些介面是分為兩類,

一類是獲取單個物件,getIfAvailable()方法用於獲取可用的bean(沒有則返回null),getIfUnique()方法用於獲取唯一的bean(如果bean不是唯一的或者沒有首選的bean返回null)。getIfAvailable(Supplier<T> defaultSupplier)和getIfUnique(Supplier<T> defaultSupplier),如果沒有獲取到bean,則返回defaultSupplier提供的預設值,ifAvailable(Consumer<T> dependencyConsumer)和ifUnique(Consumer<T> dependencyConsumer)提供了以函數語言程式設計的方式去消費獲取到的bean。

另一類是獲取多個物件,stream()方法返回連續的Stream,不保證bean的順序(通常是bean的註冊順序)。orderedStream()方法返回連續的Stream,預先會根據工廠的公共排序比較器進行排序,一般是根據org.springframework.core.Ordered的約定進行排序。

其他的是一些工具性的方法:

通過名字判斷是否包含指定bean的定義的containsBean(String name)方法

判斷是單例和原型的isSingleton(String name)和isPrototype(String name)方法

判斷給定bean的名字是否和型別匹配的isTypeMatch方法

根據bean的名字來獲取其型別的getType(String name)方法

根據bean的名字來獲取其別名的getAliases(String name)方法

或許你已經注意到了,有兩個方法含有型別是ResolvableType的引數,那麼ResolvableType是什麼呢?假如說你要獲取泛型型別的bean:MyBean<TheType>,根據Class來獲取,肯定是滿足不了要求的,泛型在編譯時會被擦除。使用ResolvableType就能滿足此需求,程式碼如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

ResolvableType type = ResolvableType.forClassWithGenerics(MyType.class, TheType.class); ObjectProvider<MyType<TheType>> op = applicationContext.getBeanProvider(type); MyType<TheType> bean = op.getIfAvailable()

簡單的來說,ResolvableType是對Javajava.lang.reflect.Type的封裝,並且提供了一些訪問該型別的其他資訊的方法(例如父類, 泛型引數,該類)。從成員變數、方法引數、方法返回型別、類來構建ResolvableType的例項。

ListableBeanFactory

ListableBeanFactory介面有能列出工廠中所有的bean的能力,下面給出該介面中的所有方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

`boolean containsBeanDefinition(String beanName); // 是否包含給定名字的bean的定義

int getBeanDefinitionCount(); // 工廠中bean的定義的數量

String[] getBeanDefinitionNames(); // 工廠中所有定義了的bean的名字

// 獲取指定型別的bean的名字

String[] getBeanNamesForType(ResolvableType type);

String[] getBeanNamesForType(Class type);

String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);

// 獲取所有使用提供的註解進行標註的bean的名字

String[] getBeanNamesForAnnotation(Class annotationType);

// 查詢指定bean中的所有指定的註解(會考慮介面和父類中的註解)

A findAnnotationOnBean(String beanName, Class annotationType)

throws NoSuchBeanDefinitionException;

// 根據指定的型別來獲取所有的bean

Map getBeansOfType(Class type) throws BeansException;

Map getBeansOfType(Class type, boolean includeNonSingletons, boolean allowEagerInit)

throws BeansException;

// 獲取所有使用提供的註解進行標註了的bean

Map getBeansWithAnnotation(Class annotationType) throws BeansException;`

上面的這些方法都不考慮祖先工廠中的bean,只會考慮在當前工廠中定義的bean。

前八個方法用於獲取bean的一些資訊

最後的三個方法用於獲取所有滿足條件的bean,返回結果Map中的鍵為bean的名字,值為bean的例項。這些方法都會考慮通過FactoryBean建立的bean,這也意味著FactoryBean會被初始化。為什麼這裡的三個方法不返回List?Map不光包含這些bean的例項,而且還包含bean的名字,而List只包含bean的例項。也就是說Map比List更加的通用。

HierarchicalBeanFactory

HierarchicalBeanFactory介面定義了BeanFactory之間的分層結構,ConfigurableBeanFactory中的setParentBeanFactory方法能設定父級的BeanFactory,下面列出了HierarchicalBeanFactory中定義的方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

BeanFactory getParentBeanFactory(); // 獲取父級的BeanFactory // 本地的工廠是否包含指定名字的bean boolean containsLocalBean(String name);

這兩個方法都比較直接明瞭,getParentBeanFactory方法用於獲取父級BeanFactory。containsLocalBean

用於判斷本地的工廠是否包含指定的bean,忽略在祖先工廠中定義的bean。

MessageSource

MessageSource主要用於訊息的國際化,下面是該介面中的方法定義:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

// 獲取訊息 String getMessage(String code, Object[] args, String defaultMessage, Locale locale); String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException; String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

以上的三個方法都是用於獲取訊息的,第一個方法提供了預設訊息,第二個介面如果沒有獲取到指定的訊息會丟擲異常。第三個介面中的MessageSourceResolvable引數是對程式碼、引數值、預設值的一個封裝。

ApplicationEventPublisher

ApplicationEventPublisher介面封裝了事件釋出功能,提供Spring中事件的機制。介面中的方法定義如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

// 釋出事件 void publishEvent(ApplicationEvent event); void publishEvent(Object event);

第一個方法用於釋出特定於應用程式事件。第二個方法能釋出任意的事件,如果事件不是ApplicationEvent,那麼會被包裹成PayloadApplicationEvent事件。

EnvironmentCapable

EnvironmentCapable提供了訪問Environment的能力,該介面只有一個方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

Environment getEnvironment();

Environment表示當前正在執行的應用的環境變數,它分為兩個部分:profiles和properties。它的父級介面PropertyResolver提供了property的訪問能力。

ResourceLoader和ResourcePatternResolver

先來看一下ResourceLoader,該介面是用來載入資源(例如類路徑或者檔案系統中的資源)的策略介面。該介面中的方法如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

Resource getResource(String location); // 根據指定的位置獲取資源 ClassLoader getClassLoader(); // 獲取該資源載入器所使用的類載入器

該介面只有簡單明瞭的兩個方法,一個是用來獲取指定位置的資源,一個用於獲取資源載入器所使用的類載入器。Resource是從實際型別的底層資源(例如檔案、類路徑資源)進行抽象的資源描述符。先看下Resource中的方法:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

`boolean exists(); // 資源實際上是否存在

boolean isReadable(); // 資源是否可讀

boolean isOpen(); // 檢查資源是否為開啟的流

boolean isFile(); // 資源是否為檔案系統上的一個檔案

URL getURL() throws IOException; // 獲取url

URI getURI() throws IOException; // 獲取URI

File getFile() throws IOException; // 獲取檔案

ReadableByteChannel readableChannel() throws IOException; // 獲取ReadableByteChannel

long contentLength() throws IOException; // 資源的內容的長度

long lastModified() throws IOException; // 資源的最後修改時間

// 相對於當前的資源建立一個新的資源

Resource createRelative(String relativePath) throws IOException;

String getFilename(); // 獲取資源的檔名

String getDescription(); // 獲取資源的描述資訊`

Resource的父級介面InputStreamSource,可以簡單的理解為InputStream的來源,只有一個方法,如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

InputStream getInputStream() throws IOException; // 獲取輸入流

接下來在來看一下ResourcePatternResolver,該介面用於解析一個位置模式(例如Ant風格的路徑模式),該介面只有一個方法,如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

// 將給定的位置模式解析成資源物件 Resource[] getResources(String locationPattern) throws IOException;

Spring IoC容器設計覆盤

假如讓你設計IoC容器,你該如何去做呢?首先你應該要明確你設計的容器的功能和特性,然後根據這些功能和特性設計出合理的介面。下面只是粗略的分析一下:

IoC容器對bean的配置和管理,那麼是不是需要設計一個介面來完成這些功能呢?(BeanFactory)

既然需要這些元資料的配置,那麼是不是需要設計一個介面來完成對一些配置檔案的讀取。(ResourceLoader和Resource)

在IoC容器初始化、摧毀的時候,是不是可能要執行一些操作呢?那麼是不是需要使用事件機制來完成呢?(ApplicationEventPublisher)

....

本文思維導圖

最後給大家推薦一個架構技術交流群: 705127209,裡面會分享一些資深架構師錄製的視訊錄影:有Spring,MyBatis,Netty原始碼分析

,高併發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,相信對於已經工作

和遇到技術瓶頸的碼友,在這個群裡會有你需要的內容。

 

相關推薦

Spring原始碼閱讀-IoC容器解析

目錄 Spring IoC容器 ApplicationContext設計解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory

Spring原始碼閱讀-IOC 容器解析

在Spring框架中最重要的是Spring IoC容器,它是Spring框架的核心。本文將從更高的角度來解析Sping IoC容器

Spring原始碼分析——IOC容器

1、IOC容器的概念 理解IOC容器的概念之前首先需要了解依賴翻轉(又稱依賴倒置)的概念 許多複雜的應用都是通過多個類之間的彼此合作實現業務邏輯的,這使得每個物件都需要管理自己與其合作物件的依賴,而如果這個過程如果交給物件自身實現將會導致程式碼的耦合度過高。因此

spring 原始碼分析--IOC容器初始化六

 上一節將xml文件解析為DOM ,並且建立了一個 BeanDefinitionParserDelegate 型別的物件,在這一節,將使用這個物件來完成對bean的裝載工作。 2.1.1.1 parseBeanDefinitions (root, delegate): 該方法體完成註冊過程。

Spring原始碼閱讀IOC核心容器基礎和繼承體系結構

BeanFactory BeanFacotry作為Spring的根容器物件,提供了對Bean的基礎操作功能,包括例項化、配置、管理Bean等。 ApplicationContext ApplicationContext對BeanFactory進行了進一步地封裝,內建了Bean

Spring原始碼閱讀——bean的載入過程解析

前言 在上一節中,我們已經瞭解過Spring對bean從XML中提取,並且以BeanDefinition型別解析註冊到Spring的DefaultListableBeanFactory中取了,那麼,接下來就應該來看下我們在Spring中獲取一個例項過程中,bean是如何載入成為我們需

spring原始碼閱讀(1)- ioc依賴注入之bean載入

還是先看下DefaultListableBeanFactory的類結構圖  我們從User user = (User) beanFactory.getBean("user");入手進入bean的載入管理流程。 這裡還是堅持走主線的流程,去掉無關的枝葉,儘量讓業務變得簡

spring原始碼閱讀(2)-aop之jdk動態代理深入解析

續spring原始碼閱讀(2)-aop之j動態代理 我們從需求作為動態代理髮展的切入吧 現在有5個已經投產了的run100m的實現,我們新的需求需要監控不同實現的執行效能,如果我們針對這五個實現分別去新增效能監控的程式碼,如此就造成兩個問題: 一個是已經穩定的程式碼需要

spring原始碼閱讀(2)-aop之原始碼解析

經過一個aop術語介紹和動態代理的深入講解,我們終於可以來看aop的原始碼了,下面跟著博主一點點剖析spring aop原始碼的實現吧 我們知道spring使用中我們只要做好相關的配置,spring自動幫我們做好了代理的相關工作。 我們從三個方面入手吧 1、配置 2、

Spring原始碼閱讀】populateBean實現 依賴注入原始碼解析

在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean方法完成。 測試程式碼 下面開始進入原始碼分析之前,先基於以下例項進行: /

Spring原始碼閱讀Spring容器初始化流程

文章目錄 refresh方法原始碼 prepareRefresh實現 obtainFreshBeanFactory實現 refreshBeanFactory方法實現 prepareBeanFactory方法實現 invokeBeanFa

Spring原始碼解析(一)】Idea搭建Spring原始碼閱讀環境

準備階段 Idea Gradle Git jdk 詳細步驟 以上工具安裝好,這裡主要記錄一下Git和Gradle,工作一直都是用的svn和Maven,所以對於Git和Gradle瞭解的不算多。 (1) Gradle安裝        Gradle的安裝很簡單,和

Spring技術內幕》學習筆記4——IoC容器解析Bean定義資源並註冊解析後的Bean

原文連結http://blog.csdn.net/chjttony/article/details/6261708 1.通過前兩篇部落格的分析,我們已經瞭解了Spring IoC容器定位和載入Bean定義資原始檔的基本過程,接下來我們要繼續分析Spring IoC容器將載

spring原始碼分析-web容器初始化過程解析1

   在之前的“”中分析了spring mvc的初始化過程,接下來將分析其請求處理過程。         在找請求處理的入口時,我們需要先知道Servlet的程式設計規範,對應不同的請求(如POST、GET等)的實現方法在FrameworkServlet中,分別是doP

Spring原始碼閱讀筆記05:自定義xml標籤解析

  在上篇文章中,提到了在Spring中存在預設標籤與自定義標籤兩種,並且詳細分析了預設標籤的解析,本文就來分析自定義標籤的解析,像Spring中的AOP就是通過自定義標籤來進行配置的,這裡也是為後面學習AOP原理打下基礎。   這裡先回顧一下,當Spring完成了從配置檔案到Document的轉換並提取對應

使用Spring.NET的IoC容器

frame 管理 sdn detail lns string creat ack mod 使用Spring.NET的IoC容器 0. 輔助類庫 using System; using System.Collections.Generic; using System.Lin

Spring框架——關於IOC容器和註解的36個小實驗

web beans count 註入 定義 目標 初始化 getc pan 實驗1:通過IOC容器創建對象,並為屬性賦值★ <bean id="page" class="com.neuedu.Bean.Page"> <property name="f

Spring原始碼閱讀——ApplicationContext

Spring中提供了一個介面ApplicationContext,用於擴充套件BeanFactory中現有的功能。它提供了更多的功能。現在我們來看下它的實現: public ClassPathXmlApplicationContext(String[] configLocat

Spring原始碼閱讀——BeanFactoryPostProcessor與BeanPostProcessor

摘要 Spring IoC容器允許BeanFactoryPostProcessor在容器例項化任何bean之前讀取bean的定義(配置元資料),並可以修改它。 BeanFactoryPostProcessor: BeanFactory的後置處理器(處理的物件是BeanFact

Spring原始碼初探-IOC(4)-Bean的初始化-迴圈依賴的解決

前言 在實際工作中,經常由於設計不佳或者各種因素,導致類之間相互依賴。這些類可能單獨使用時不會出問題,但是在使用Spring進行管理的時候可能就會丟擲BeanCurrentlyInCreationException等異常 。當丟擲這種異常時表示Spring解決不了該迴圈依賴,本文將簡要說明Spr