天天看點

Spring容器文檔閱讀要點記錄

容器代碼位于 <code>org.springframework.beans</code> 和 <code>org.springframework.context</code>包下面

基本接口:BeanFactory,ApplicationContext 是BeanFactory的子接口,提供了企業級應用的功能,擁有更加進階的功能

平常的業務開發基本上都是層ApplicationContext的的實作類開始,因為其提供了功能強大的實作

常用的容器實作類:

Web類:

XmlWebApplicationContext

AnnotationConfigWebApplicationContext

GroovyWebApplicationContext

非Web類:

ClassPathXmlApplicationContext

GenericXmlApplicationContext

AnnotationConfigApplicationContext

GenericGroovyApplicationContext

FileSystemXmlApplicationContext

BeanDefinition用于存放Bean的定義元資訊

Spring容器的的MetaData定義和具體的元資訊的定義形式無關,是完全解耦的。支援XML,注解,Java配置類都可以用于定于Spring容器都元資訊。Spring2.5開始支援注解,Spring3.0開始支援基于Java配置類的元資訊定義

容器中記錄了BeanDefinition用于定義Bean的定義和其它一些資訊,包括:

包限定的類

Bean的名字

作用域

構造器參數

Bean行為定義,包含Scope,lifeCycle callbacls等

依賴的其它Bean

其它一些設定資訊

Spring容器文檔閱讀要點記錄

常見的實作類:

AnnotatedGenericBeanDefinition:可以讀取注解來定義元資訊的BeanDefinition

RootBeanDefinition:能夠單獨作為一個BeanDefinition,或者是别的BeanDefinition的父定義,但不能作為一個BeanDefinition的子定義

ChildBeanDefinition:不能單獨作為一個BeanDefinition,必須要依賴一個父BeanDefinition

ConfigurationClassBeanDefinition:是一個為Java的配置類生成的過渡性BeanDefinition,用于确定一個Bean是否需要覆寫另一個Bean的情況

ScannedGenericBeanDefinition:和AnnotatedGenericBeanDefinition功能差不多,但是增加了掃描.Class的特性

BeanDefinitionReader用于讀取不同種類的容器定義形式的中繼資料的接口

有實作類:

GroovyBeanDefinitionReader:通過Groovy的的方式定義元資訊

PropertiesBeanDefinitionReader:通過Property格式定義中繼資料

XmlBeanDefinitionReader:常用的通過XML的格式定義中繼資料

初始化容器

讀取Bean的定義資料,生成<code>BeanDifinition</code>并緩存到BeanFactory中

完成初始化容器,回調<code>BeanFactoryPostProcessor</code>接口的實作類的<code>postProcessBeanFactory</code>

容器開始周遊緩存的<code>BeanDifinition</code>集合并執行個體化非懶加載的Bean(如果是懶加載,則在主動向容器擷取的時候開始Bean生命周期)

執行個體化Bean,如果是構造器注入依賴則使用指定的構造器執行執行個體化操作

設定對象屬性,通過反射調用<code>setXXX()</code>方法将依賴的Bean注入

檢查目前的Bean是否實作了各種,*Aware相關接口。如<code>ApplicationContextAware</code>,<code>BeanNameAware</code>,<code>BeanClassLoaderAware</code>等。如果實作就調用相關方法

将目前Bean的執行個體作為參數調用一系列的<code>BeanPostProcessor</code>接口的實作類的<code>postProcessBeforeInitialization</code>前置處理方法

檢查目前Bean的是否實作了<code>InitializingBean</code>接口,如果實作了就調用<code>afterPropertiesSet</code>方法

檢查是否有自定義的<code>init-method</code>或者Bean中有被<code>@PostConstruct</code>注解的方法,有就調用

将目前Bean的執行個體作為參數調用一系列的<code>BeanPostProcessor</code>接口的實作類的<code>postProcessAfterInitialization</code>後置處理方法

注冊必要的Destruction相關回調接口

正常使用中

當Application關閉的時候,檢查Bean是否實作了<code>DisposableBean</code>接口,有就調用<code>destroy</code>方法

檢查Bean是否有配置自定義的 <code>destroy-method</code>方法或者<code>@PreDestroy</code>注解的方法,有就調用。另外Spring的容器會自動調用實作了<code>java.lang.AutoCloseable</code> 或者<code>java.io.Closeable</code>的Bean的接口

Application關閉成功

有以下3類擴充方法,用于不同的生命周期節點和不同的作用域

普通接口:InitializingBean,DisposableBean

各種Aware接口:ApplicationContextAware, BeanNameAware, BeanClassLoaderAware等

特殊的接口:Lifecycle,LifecycleProcessor

其它的一些Aware類型接口都可以用于Bean的實作

Spring容器文檔閱讀要點記錄

BeanPostProcessor接口用于在Spring容器初始化執行個體後的一些回調方法,可用于自定義Bean初始化業務邏輯。

Spring-Aop的應用:

在AOP程式設計中,要實作AOP有兩種方式,如果是按接口注入的方式,那麼可以使用JDK的動态代理生成代理類。如果按類注入的方式,就需要CGLIB來生成位元組碼注入的方式來生成代理類。而上面兩種方式的共同點都是要向使用者隐瞞真實的類型資訊,讓使用者認為代理類就是被代理類本身。這個過程就可以通過BeanPostProcessor的回調函數進行操作,生成代理類後直接傳回該代理類到容器中,容器會認為該代理類是代理類本身。在注入的時候,就會把代理類注入。

BeanFactoryPostProcessor接口用于在容器初始化并加載完所有BeanDefinition後初始化執行個體之前。在這裡我們可以自定義的去配置Bean的元資訊,也就是BeanDefinition。

Ordered接口是用于排序BeanPostProcessor和BeanFactoryPostProcessor的實作類的。如果存在多個BeanPostProcessor和BeanFactoryPostProcessor。那麼,Spring會使用Ordered接口來給多個處理器進行排序,按從小到大的順序進行處理

一類特殊的Bean,其作用完全是為了生産目标Bean而存在,我們通過容器擷取目标Bean的時候,容器會通過工廠Bean來生産目标Bean。

FactoryBean是一個特殊的接口,如果一個Bean實作了FactoryBean接口。那麼該Bean是目标Bean的工廠Bean。我們使用容器去getBean時候,容器會去調用目前工廠Bean的getObject()方法,在getObject()中我們可以自定義初始化一個Class的執行個體,傳回的對象作為目标Bean本身。在目标Bean初始化邏輯非常複雜的情況下,FactoryBean接口是一個非常有用的接口,它可以幫助我們去自定義一個Bean的初始化過程。這個作用和@Bean注解的方法非常相似,差別在于FactoryBean傳回的目标Bean沒有SpringBean的生命周期,而@Bean傳回的目标Bean是擁有完整的Bean生命周期的。@Bean常常用于@Configuration類中,适合在Application層面的配置。但作為庫的程式推薦使用FactoryBean接口的方式。以免和庫的使用者的配置發生沖突。

對于getObject()暴露出去的執行個體最好在<code>FactoryBean</code>類中儲存一下引用關系,因為通過<code>FactoryBean</code>的工廠Bean暴露出去的目标Bean是不存在Spring IoC容器Bean的生命周期的,如果要應用程式關閉後,目标Bean需要做一些資源回收的操作隻能在工廠Bean中做,工廠Bean是擁有SpringBean的完整生命周期的,如果工廠Bean中沒有緩存對目标Bean的引用關系,那麼沒有辦法做到目标Bean的資源回收。

需要自定義讀取一個properties配置檔案的時候的可以使用兩種方式:

上面兩種方式的檔案都放置在Resources目錄下面

注解的方式:

Spring的AOP是一個通用的切面程式設計封裝。它封裝了結合JDK動态代理和CGLIB的基于類的代理使用方式。根據不同的情況,Spring會自動的選擇适合的切面實作方式和提供統一的使用方式,既通過<code>ProxyFactory</code>代理工廠類來生成代理對象。

Spring中如何生成使用AOP程式設計?有兩種方式:一種是結合IoC容器的實作,另一種是基于程式設計的實作<code>ProxyFactory</code>類通過程式設計來生成代理類

1.聲明Advice類,使用@Aspect

2.聲明Advice方法

可以使用的Advice:

@Before:被代理方法被執行的通知

@AfterReturning:在被代理方法執行後通知

@AfterThrowing:在被代理方法抛出異常後通知

@After:在被代理方法執行後,無論是否傳回或者抛出異常都通知

@Around:環繞通知,帶被代理方法的前後都能被通知

3.聲明切點常用的幾種方式:

execution表達式

@annotation表達式

如果一個類的作用域不是singleton單例的情況下,其作為一個單例的一個依賴的情況下,必須制定代理模式為:INTERFACES或TARGET_CLASS。如果目前類是按接口類型注入的,那就可以使用INTERFACES作為代理模式,Spring會基于該接口生産動态代理類。如果目前類沒有接口實作,那就需要指定代理模式為TARGET_CLASS,Spring會使用CGLIB生成代理類。因為作為單例類的依賴類,在單例類完成Bean的初始話後,屬性就固定了。是以為了每次都能調用到不同Scope的Bean需要代理類來實作代理才能實作。

由于掃描一些自定義的類并把他注冊到容器中

Spring容器文檔閱讀要點記錄

@Bean注解需要在@Configuration聲明的類中使用,特别需要依賴容器中的其它Bean的時候。需特别注意依賴Bean的注入方式。如果在非@Configuration的類中使用@Bean注解方法,那麼這樣無法保證目前@Bean傳回的目标Bean的依賴關系。需要在目前的類内部進行依賴的保證。是以建議@Bean注解需要在@Configuration聲明的類中使用。

因為使用@Configuration的類在容器初始化之後會很早被執行,如果通過@Autowired或者@Value使用注入的話可能會導緻一些意想不到的異常,建議通過方法的參數注入依賴Bean。

還有要注意的是。如果使用@Bean修飾的方法傳回的是自定義的BeanPostProcessor或者BeanFactoryPostPorcessor的話,需要使用靜态方法來提升方法運作的優先級,因為@Configuration自己本身就是一個Bean。如果說在@Configuration執行個體化時候,才執行個體化自定義的BeanPostProcessor或者BeanFactoryPostPorcessor的話可能會導緻一些Bean不能被正确的處理。

壞的依賴注入示例:

好的依賴注入示例:

沐風的原創文章

繼續閱讀