容器代碼位于 <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
其它一些設定資訊

常見的實作類:
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的實作
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需要代理類來實作代理才能實作。
由于掃描一些自定義的類并把他注冊到容器中
@Bean注解需要在@Configuration聲明的類中使用,特别需要依賴容器中的其它Bean的時候。需特别注意依賴Bean的注入方式。如果在非@Configuration的類中使用@Bean注解方法,那麼這樣無法保證目前@Bean傳回的目标Bean的依賴關系。需要在目前的類内部進行依賴的保證。是以建議@Bean注解需要在@Configuration聲明的類中使用。
因為使用@Configuration的類在容器初始化之後會很早被執行,如果通過@Autowired或者@Value使用注入的話可能會導緻一些意想不到的異常,建議通過方法的參數注入依賴Bean。
還有要注意的是。如果使用@Bean修飾的方法傳回的是自定義的BeanPostProcessor或者BeanFactoryPostPorcessor的話,需要使用靜态方法來提升方法運作的優先級,因為@Configuration自己本身就是一個Bean。如果說在@Configuration執行個體化時候,才執行個體化自定義的BeanPostProcessor或者BeanFactoryPostPorcessor的話可能會導緻一些Bean不能被正确的處理。
壞的依賴注入示例:
好的依賴注入示例:
沐風的原創文章