spring原理(一)

它是一個全面的、企業應用開發一站式的解決方案,貫穿表現層、業務層、持久層。但是 Spring仍然可以和其他的框架無縫整合。

1. Spring 特點

   1.輕量級

   2.控制反轉

   3.面向切面

   4.容器

   5.框架集合

2. Spring 核心組件

3. Spring 常用模塊

4. Spring 主要包

5. Spring 常用註解

bean 注入與裝配的的方式有很多種,可以通過 xml,get set 方式,構造函數或者註解等。簡單易用的方式就是使用 Spring 的註解了,Spring 提供了大量的註解方式。

 

6. Spring 第三方結合

 

7. Spring IOC 原理

    ​1. 概念

    ​Spring 通過一個配置文件描述 Bean 及 Bean 之間的依賴關係,利用 Java 語言的反射功能實例化Bean 並建立 Bean 之間的依賴關係。 Spring 的 IoC 容器在完成這些底層工作的基礎上,還提供了 Bean 實例緩存、生命週期管理、 Bean 實例代理、事件發佈、資源裝載等高級服務。

    ​2. Spring 容器高層視圖

    ​Spring 啓動時讀取應用程序提供的 Bean 配置信息,並在 Spring 容器中生成一份相應的 Bean 配置註冊表,然後根據這張註冊表實例化 Bean,裝配好 Bean 之間的依賴關係,爲上層應用提供準備就緒的運行環境。其中 Bean 緩存池爲 HashMap 實現

 

3. IOC 容器實現

BeanFactory-框架基礎設施

    ​BeanFactory 是 Spring 框架的基礎設施,面向 Spring 本身;ApplicationContext 面向使用Spring 框架的開發者,幾乎所有的應用場合我們都直接使用 ApplicationContext 而非底層的 BeanFactory。

 

1.1..1.1.1 BeanDefinitionRegistry 註冊表

   1. Spring 配置文件中每一個節點元素在 Spring 容器裏都通過一個 BeanDefinition 對象表示,它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工註冊BeanDefinition 對象的方法。

1.1..1.1.2 BeanFactory 頂層接口

    ​2. 位於類結構樹的頂端 ,它最主要的方法就是 getBean(String beanName),該方法從容器中返回特定名稱的 Bean,BeanFactory 的功能通過其他的接口得到不斷擴展:

1.1..1.1.3 ListableBeanFactory

    ​3. 該接口定義了訪問容器中 Bean 基本信息的若干方法,如查看 Bean 的個數、獲取某一類型Bean 的配置名、查看容器中是否包括某一 Bean 等方法;

1.1..1.1.4 HierarchicalBeanFactory 父子級聯

    ​4. 父子級聯 IoC 容器的接口,子容器可以通過接口方法訪問父容器; 通過HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子層級關聯的容器體系,子容器可以訪問父容器中的 Bean,但父容器不能訪問子容器的 Bean。Spring 使用父子容器實現了很多功能,比如在 Spring MVC 中,展現層 Bean 位於一個子容器中,而業務層和持久層的 Bean 位於父容器中。這樣,展現層 Bean 就可以引用業務層和持久層的 Bean,而業務層和持久層的 Bean 則看不到展現層的 Bean。

1.1..1.1.5 ConfigurableBeanFactory

    ​5. 是一個重要的接口,增強了 IoC 容器的可定製性,它定義了設置類裝載器、屬性編輯器、容器初始化後置處理器等方法;

1.1..1.1.6 AutowireCapableBeanFactory 自動裝配

    ​6. 定義了將容器中的 Bean 按某種規則(如按名字匹配、按類型匹配等)進行自動裝配的方法;

1.1..1.1.7 SingletonBeanRegistry 運行期間註冊單例 Bean

    ​7. 定義了允許在運行期間向容器註冊單實例 Bean 的方法;對於單實例( singleton)的 Bean 來說,BeanFactory 會緩存 Bean 實例,所以第二次使用 getBean() 獲取 Bean 時將直接從IoC 容器的緩存中獲取 Bean 實例。Spring 在 DefaultSingletonBeanRegistry 類中提供了一個用於緩存單實例 Bean 的緩存器,它是一個用 HashMap 實現的緩存器,單實例的 Bean 以beanName 爲鍵保存在這個 HashMap 中。

1.1..1.1.8 依賴日誌框框

    ​8. 在初始化 BeanFactory 時,必須爲其提供一種日誌框架,比如使用 Log4J, 即在類路徑下提供 Log4J 配置文件,這樣啓動 Spring 容器纔不會報錯。

ApplicationContext 面向開發應用

ApplicationContext 由 BeanFactory 派生而來,提供了更多面向實際應用的功能。ApplicationContext 繼承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此基礎上,還通過多個其他的接口擴展了 BeanFactory 的功能:

1. ClassPathXmlApplicationContext:默認從類路徑加載配置文件

2. FileSystemXmlApplicationContext:默認從文件系統中裝載配置文件

3. ApplicationEventPublisher:讓容器擁有發佈應用上下文事件的功能,包括容器啓動事件、關閉事件等。

4. MessageSource:爲應用提供 i18n 國際化消息訪問的功能;

5. ResourcePatternResolver : 所 有 ApplicationContext 實現類都實現了類似於PathMatchingResourcePatternResolver 的功能,可以通過帶前綴的 Ant 風格的資源文件路徑裝載 Spring 的配置文件。

6. LifeCycle:該接口是 Spring 2.0 加入的,該接口提供了 start()和 stop()兩個方法,主要用於控制異步處理過程。在具體使用時,該接口同時被 ApplicationContext 實現及具體Bean 實現, ApplicationContext 會將 start/stop 的信息傳遞給容器中所有實現了該接口的 Bean,以達到管理和控制 JMX、任務調度等目的。

7. ConfigurableApplicationContext 擴展於 ApplicationContext,它新增加了兩個主要的方法: refresh()和 close(),讓 ApplicationContext 具有啓動、刷新和關閉應用上下文的能力。在應用上下文關閉的情況下調用 refresh()即可啓動應用上下文,在已經啓動的狀態下,調用 refresh()則清除緩存並重新裝載配置信息,而調用 close()則可關閉應用上下文。

WebApplication 體系架構

    ​WebApplicationContext 是專門爲 Web 應用準備的,它允許從相對於 Web 根目錄的路徑中裝載配置文件完成初始化工作。從 WebApplicationContext 中可以獲得ServletContext 的引用,整個 Web 應用上下文對象將作爲屬性放置到 ServletContext 中,以便 Web 應用環境可以訪問 Spring 應用上下文。

4. Spring Bean 作用域

Spring 3 中爲 Bean 定義了 5 中作用域,分別爲 singleton(單例)、prototype(原型)、request、session 和 global session,5 種作用域說明如下:

singleton:單例模式(多線程下不安全)

1. singleton:單例模式,Spring IoC 容器中只會存在一個共享的 Bean 實例,無論有多少個Bean 引用它,始終指向同一對象。該模式在多線程下是不安全的。Singleton 作用域是Spring 中的缺省作用域,也可以顯示的將 Bean 定義爲 singleton 模式,配置爲:<bean id="userDao" class="com.ioc.UserDaoImpl" scope="singleton"/>

prototype:原型模式每次使用時創建

2. prototype:原型模式,每次通過 Spring 容器獲取 prototype 定義的 bean 時,容器都將創建一個新的 Bean 實例,每個 Bean 實例都有自己的屬性和狀態,而 singleton 全局只有一個對象。根據經驗,對有狀態的bean使用prototype作用域,而對無狀態的bean使用singleton作用域。

Request:一次 request 一個實例

3. request:在一次 Http 請求中,容器會返回該 Bean 的同一實例。而對不同的 Http 請求則會產生新的 Bean,而且該 bean 僅在當前 Http Request 內有效,當前 Http 請求結束,該 bean實例也將會被銷燬。

<bean id="loginAction" class="com.cnblogs.Login" scope="request"/>

session

4. session:在一次 Http Session 中,容器會返回該 Bean 的同一實例。而對不同的 Session 請求則會創建新的實例,該 bean 實例僅在當前 Session 內有效。同 Http 請求相同,每一次session 請求創建新的實例,而不同的實例之間不共享屬性,且實例僅在自己的 session 請求內有效,請求結束,則實例將被銷燬。

<bean id="userPreference" class="com.ioc.UserPreference" scope="session"/>

global Session

5. global Session:在一個全局的 Http Session 中,容器會返回該 Bean 的同一個實例,僅在使用 portlet context 時有效。

 

5. Spring Bean 生命週期

實例化

1. 實例化一個 Bean,也就是我們常說的 new。

 

IOC 依賴注入

    ​2. 按照 Spring 上下文對實例化的 Bean 進行配置,也就是 IOC 注入

 

setBeanName 實現

3. 如果這個 Bean 已經實現了 BeanNameAware 接口,會調用它實現的 

setBeanName(String)方法,此處傳遞的就是 Spring 配置文件中 Bean 的 id 值

 

BeanFactoryAware 實現

4. 如果這個 Bean 已經實現了 BeanFactoryAware 接口,會調用它實現的 setBeanFactory,setBeanFactory(BeanFactory)傳遞的是 Spring 工廠自身(可以用這個方式來獲取其它 Bean,只需在 Spring 配置文件中配置一個普通的 Bean 就可以)。

 

ApplicationContextAware 實現

5. 如果這個 Bean 已經實現了 ApplicationContextAware 接口,會調用setApplicationContext(ApplicationContext)方法,傳入 Spring 上下文(同樣這個方式也可以實現步驟 4 的內容,但比 4 更好,因爲 ApplicationContext 是 BeanFactory 的子接口,有更多的實現方法)

 

postProcessBeforeInitialization 接口實現-初始化預處理

6. 如果這個 Bean 關聯了 BeanPostProcessor 接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 經常被用作是 Bean 內容的更改,並且由於這個是在 Bean 初始化結束時調用那個的方法,也可以被應用於內存或緩存技術。

 

init-method

7. 如果 Bean 在 Spring 配置文件中配置了 init-method 屬性會自動調用其配置的初始化方法。

 

postProcessAfterInitialization

8. 如果這個 Bean 關聯了 BeanPostProcessor 接口,將會調用postProcessAfterInitialization(Object obj, String s)方法。注:以上工作完成以後就可以應用這個 Bean 了,那這個 Bean 是一個 Singleton 的,所以一般情況下我們調用同一個 id 的 Bean 會是在內容地址相同的實例,當然在 Spring 配置文件中也可以配置非 Singleton。

Destroy 過期自動清理階段

9. 當 Bean 不再需要時,會經過清理階段,如果 Bean 實現了 DisposableBean 這個接口,會調用那個其實現的 destroy()方法;

destroy-method 自配置清理

10. 最後,如果這個 Bean 的 Spring 配置中配置了 destroy-method 屬性,會自動調用其配置的銷燬方法。

11. bean 標籤有兩個重要的屬性(init-method 和 destroy-method)。用它們你可以自己定製初始化和註銷方法。它們也有相應的註解(@PostConstruct 和@PreDestroy)。<bean id="" class="" init-method="初始化方法" destroy-method="銷燬方法">

 

6. Spring 依賴注入四種方式

構造器注入

/*帶參數,方便利用構造器進行注入*/  public CatDaoImpl(String message){  this. message = message;  } <bean id="CatDaoImpl" class="com.CatDaoImpl"> <constructor-arg value=" message "></constructor-arg> </bean>

setter 方法注入

public class Id {  private int id;  public int getId() { return id; }  public void setId(int id) { this.id = id; } } <bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>

靜態工廠注入

靜態工廠顧名思義,就是通過調用靜態工廠的方法來獲取自己需要的對象,爲了讓 spring 管理所有對象,我們不能直接通過"工程類.靜態方法()"來獲取對象,而是依然通過 spring 注入的形式獲取:

public class DaoFactory { //靜態工廠  public static final FactoryDao getStaticFactoryDaoImpl(){  return new StaticFacotryDaoImpl();  } } public class SpringAction {  private FactoryDao staticFactoryDao; //注入對象 //注入對象的 set 方法  public void setStaticFactoryDao(FactoryDao staticFactoryDao) {  this.staticFactoryDao = staticFactoryDao;  } } //factory-method="getStaticFactoryDaoImpl"指定調用哪個工廠方法 <bean name="springAction" class=" SpringAction" >  <!--使用靜態工廠的方法注入對象,對應下面的配置文件-->  <property name="staticFactoryDao" ref="staticFactoryDao"></property>  </bean> <!--此處獲取對象的方式是從工廠類中獲取靜態方法--> <bean name="staticFactoryDao" class="DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

實例工廠

實例工廠的意思是獲取對象實例的方法不是靜態的,所以你需要首先 new 工廠類,再調用普通的實例方法:

public class DaoFactory { //實例工廠  public FactoryDao getFactoryDaoImpl(){  return new FactoryDaoImpl(); } } public class SpringAction {  private FactoryDao factoryDao; //注入對象  public void setFactoryDao(FactoryDao factoryDao) {  this.factoryDao = factoryDao;  } }  <bean name="springAction" class="SpringAction">  <!--使用實例工廠的方法注入對象,對應下面的配置文件-->  <property name="factoryDao" ref="factoryDao"></property>  </bean>  <!--此處獲取對象的方式是從工廠類中獲取實例方法--> <bean name="daoFactory" class="com.DaoFactory"></bean> <bean name="factoryDao" factory-bean="daoFactory"factory-method="getFactoryDaoImpl"></bean>

7. 5 種不同方式的自動裝配

Spring 裝配包括手動裝配和自動裝配,手動裝配是有基於 xml 裝配、構造方法、setter 方法等自動裝配有五種自動裝配的方式,可以用來指導 Spring 容器用自動裝配方式來進行依賴注入。

1. no:默認的方式是不進行自動裝配,通過顯式設置 ref 屬性來進行裝配。

2. byName:通過參數名 自動裝配,Spring 容器在配置文件中發現 bean 的 autowire 屬性被設置成 byname,之後容器試圖匹配、裝配和該 bean 的屬性具有相同名字的 bean。

3. byType:通過參數類型自動裝配,Spring 容器在配置文件中發現 bean 的 autowire 屬性被設置成 byType,之後容器試圖匹配、裝配和該 bean 的屬性具有相同類型的 bean。如果有多個 bean 符合條件,則拋出錯誤。

4. constructor:這個方式類似於 byType, 但是要提供給構造器參數,如果沒有確定的帶參數的構造器參數類型,將會拋出異常。

5. autodetect:首先嚐試使用 constructor 來自動裝配,如果無法工作,則使用 byType 方式。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章