一、首先解釋一下什麼是Spring框架,以及Spring框架的作用
1、Spring框架:Spring是一個full-stack(一站式)的輕量級開源框架,以IOC(Inverse Of Control: 控制反轉)和 AOP(Aspect Oriented Programming:面向切面編程)爲內核。簡單來說,Spring是一個分層的JavaSE/EE full-stack 輕量級開源框架。
2、作用:解決企業應用開發的複雜性
3、優點:
1):方便解耦,簡化開發 (高內聚低耦合)
Spring就是一個大工廠(容器),可以將所有對象創建和依賴關係維護,交給Spring管理
spring工廠是用於生成bean
2):AOP編程的支持
Spring提供面向切面編程,可以方便的實現對程序進行權限攔截、運行監控等功能
3):聲明式事務的支持
只需要通過配置就可以完成對事務的管理,而無需手動編程
4):方便程序的測試
Spring對Junit4支持,可以通過註解方便的測試Spring程序
5):方便集成各種優秀框架
Spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
6):降低JavaEE API的使用難度
Spring 對JavaEE開發中非常難用的一些API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些API應用難度大大降低
二、什麼是IOC?
1、IOC(Inversion of Control):就是控制反轉。控制反轉指的就是將對象的創建權交給了Spring來管理,其作用是實現了程序的解耦合(解耦)或者理解爲降低了程序間的依賴關係,從而提高程序間的獨立性,滿足開閉原則,提高了可複用性和可修改性。可以解釋爲:原始的創建對象的方法都是使用new一個對象,這樣就使得程序間的依賴關係很強,不方便修改和複用,所以我們常常採用工廠方法模式+反射+配置文件來改進,而IOC的底層原理就是使用工廠方法設計模式+反射+XML配置文件或註解來創建對象,只不過原始的創建對象的任務是交給程序員來編寫,而現在使用Spring框架後,創建對象的任務就交給了Spring來管理。
2、關於IOC的一些細節
BeanFactory是Spring的IOC核心容器中的頂層接口,ApplicationContext是BeanFactory的子接口,這兩個接口也是常用的創建bean對象的接口。
兩者的區別:
ApplicationContext:一般是單例對象使用,它在構建核心容器時,創建對象採取的策略是採用立即加載的方式。也就是說,只要一讀取完配置文件馬上就創建配置文件中配置的對象(開發通常採用這個接口)
BeanFactory:一般是多例對象使用,它在構建核心容器時,創建對象採取的策略是採用延遲加載的方式。也就是說,什麼時候根據id獲取對象了,什麼時候才真正的創建對象。
ApplicationContext常用的三個實現類:
ClassPathXmlApplicationContext:加載類路徑下的配置文件,要求配置文件必須在類路徑下。不在的話,加載不了。(常用)
FileSystemXmlApplicationContext:加載磁盤任意路徑下的配置文件(必須有訪問權限)
AnnotationConfigApplicationContext:用於讀取註解創建容器的
3、Spring對bean的管理細節
1)、創建bean對象的三種方式:
第一種方式:使用默認構造函數創建。 在spring的配置文件中使用bean標籤,配以id和class屬性之後,且沒有其他屬性和標籤時。 採用的就是默認構造函數創建bean對象,此時如果類中沒有默認構造函數,則對象無法創建。
eg:<bean id="對象名(accountService)" class="實現類的全限定類名(com.spring.service.impl.AccountServiceImpl)"></bean>
第二種方式: 使用普通工廠中的方法創建對象(使用某個類中的方法創建對象,並存入spring容器)
eg:<bean id="instanceFactory" class="com.spring.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
第三種方式:使用工廠中的靜態方法創建對象(使用某個類中的靜態方法創建對象,並存入spring容器)
eg:<bean id="accountService" class="com.spring.factory.StaticFactory" factory-method="getAccountService"></bean>
注:上面所給出的id,class,factory-bean,factory-method屬性值要根據自己的項目來寫
2)、bean的作用範圍
bean標籤的scope屬性:
作用:用於指定bean的作用範圍
取值: 常用的就是單例的和多例的
singleton:單例的(默認值)一個應用只有一個對象的實例。它的作用範圍就是整個引用。
prototype:多例的 , 每次訪問對象時,都會重新創建對象實例。
request:作用於web應用的請求範圍,web項目中,Spring 創建一個 Bean 的對象,將對象存入到 request 域中
session:作用於web應用的會話範圍,web項目中,Spring 創建一個 Bean 的對象,將對象存入到 session 域中
global-session:作用於集羣環境的會話範圍(全局會話範圍),當不是集羣環境時,它就是session
eg:<bean id="accountService" class="com.spring.service.impl.AccountServiceImpl" scope="prototype"></bean> -->
3)、bean對象的生命週期
單例對象:scope="singleton"
出生:當容器創建時對象出生
活着:只要容器還在,對象一直活着
死亡:容器銷燬,對象消亡
總結:單例對象的生命週期和容器相同
多例對象:scope="prototype"
出生:當我們使用對象時spring框架爲我們創建
活着:對象只要是在使用過程中就一直活着。
死亡:當對象長時間不用,且沒有別的對象引用時,由Java的垃圾回收器回收
eg:<bean id="accountService" class="com.spring.service.impl.AccountServiceImpl" scope="singleton" init-method="init" destroy-method="destroy"></bean>
4、spring 的依賴注入
依賴注入:(Dependency Injection)它是 spring 框架核心 ioc 的具體實現。 我們的程序在編寫時,通過控制反轉,把對象的創建交給了 spring,但是代碼中不可能出現沒有依賴的情況。 ioc 解耦只是降低他們的依賴關係,但不會消除。例如:我們的業務層仍會調用持久層的方法。 那這種業務層和持久層的依賴關係,在使用 spring 之後,就讓 spring 來維護了。 簡單的說,就是坐等框架把持久層(DAO)對象傳入業務層(Service),而不用我們自己去獲取。(再說通俗一點就是“賦值”)
能注入的數據有三類:基本類型和String 、其他bean類型(在配置文件中或者註解配置過的bean)、複雜類型/集合類型
注入的方式有三種:1)使用構造函數 2)使用set方法 3)使用註解
1)、構造函數的注入:(顧名思義,就是使用類中的構造函數,給成員變量賦值。注意,賦值的操作不是我們自己做的,而是通過配置的方式,讓 spring 框架來爲我們注入)
使用的標籤:constructor-arg
標籤出現的位置:bean標籤的內部
標籤中的屬性
type:用於指定要注入的數據的數據類型,該數據類型也是構造函數中某個或某些參數的類型
index:用於指定要注入的數據給構造函數中指定索引位置的參數賦值。索引的位置是從0開始
name:用於指定給構造函數中指定名稱的參數賦值(常用)
注:以上三個用於指定給構造函數中哪個參數賦值
value:用於提供基本類型和String類型的數據
ref:用於指定其他的bean類型數據。它指的就是在spring的Ioc核心容器中出現過的bean對象
優勢: 在獲取bean對象時,注入數據是必須的操作,否則對象無法創建成功。
弊端: 改變了bean對象的實例化方式,使我們在創建對象時,如果用不到這些數據,也必須提供。
eg:
2)set方法注入(顧名思義,就是在類中提供需要注入成員的 set 方法) 最常用的方式
涉及的標籤:property
出現的位置:bean標籤的內部
標籤的屬性
name:用於指定注入時所調用的set方法名稱
value:用於提供基本類型和String類型的數據
ref:用於指定其他的bean類型數據。它指的就是在spring的Ioc核心容器中出現過的bean對象
優勢: 創建對象時沒有明確的限制,可以直接使用默認構造函數
弊端: 如果有某個成員必須有值,則獲取對象是有可能set方法沒有執行。
eg:數據類型爲基本類型和String 、其他bean類型時:
數據類型爲複雜類型/集合類型時
三、基於註解的 IOC 配置
1、用於創建對象的
XML配置文件中:編寫一個<bean>標籤(如上創建bean對象的三種方式)
註解中:@Component註解
作用:用於把當前類對象存入spring容器中
屬性: value:用於指定bean的id。當我們不寫時,它的默認值是當前類名,且首字母改小寫。
但在三層架構中spring框架爲我們提供了具體的註解:
表現層:@Controller
業務層:@Service
持久層:@Repository
注:以上三個註解他們的作用和屬性與Component是一模一樣。
2、用於注入數據的
XML配置文件中:如上的三種方式,constructor-arg、property
註解中:
1):@Autowired(無屬性)
作用:自動按照類型注入。只要容器中有唯一的一個bean對象類型和要注入的變量類型匹配,就可以注入成功, 如果ioc容器
沒有任何bean的類型和要注入的變量類型匹配,則報錯(因爲IOC容器是一個Map結構)
出現的位置:可以是變量上,也可以是方法上
2):@Qualifier
作用:在按照類中注入的基礎之上再按照名稱注入。它在給類成員注入時不能單獨使用(必須結合@Autowired使用)。但是在給方法參數注入時可以
屬性:value:用於指定注入bean的id
例如:
3):@Resource
作用:直接按照bean的id注入。它可以獨立使用
屬性:name:用於指定bean的id。
注: 以上三個注入都只能注入其他bean類型的數據,而基本類型和String類型無法使用上述註解實現, 另外,集合類型的注入只能通過XML來實現。
4):@Value(可以注入基本類型和String類型的數據)
作用:用於注入基本類型和String類型的數據
屬性: value:用於指定數據的值。它可以使用spring中SpEL(也就是spring的el表達式),SpEL的寫法:${表達式}
3、用於改變作用範圍的
XML配置中:scope屬性
註解中:@Scope
作用:指定bean的作用範圍
屬性:value:指定範圍的取值。常用取值:singleton prototype(如註解一樣)
4、用於改變生命週期的
XML配置中:init-method、destroy-method屬性
註解中:
@PostConstruct:用於指定初始化方法
@PreDestroy:用於指定銷燬方法