spring的IOC,DI及案例詳解


spring的IOC,DI及案例詳解

一:spring的基本特征

 

Spring是一個非常活躍的開源框架;它是一個基於Core來架構多層JavaEE系統的框架,它的主要目的是簡化企業開發。Spring以一種非侵入式的方式來管理你的代碼,Spring提倡“最少侵入,這也意味着你可以適當的時候安裝或卸載Spring。


 二:開發Spring所需要的工具

  1.Spring的jar包

到http://www.springsource.org/download下載spring,然后進行解壓縮,在解壓目錄中找到下面jar文件,拷貝到類路徑下 

 

--spring的核心類庫 在spring文檔的dist下: dist\spring.jar
--引入的第三方類庫 都spring文檔的lib下:lib\jakarta-commons\commons-logging.jar
以上兩個jar包,是開發spring最基本的jar包。


如果使用了切面編程(AOP),還需要下列jar文件 lib/aspectj/aspectjweaver.jar和aspectjrt.jar lib/cglib/cglib-nodep-2.1_3.jar

如果使用了JSR-250中的注解,如@Resource/@PostConstruct/@PreDestroy,還需要下列jar文件 lib\j2ee\common-annotations.jar 注:JSR(Java 規范請求)是指向JCP(Java Community Process)提出新增一個標准化技術規范的正式請求。任何人都可以提交JSR(Java 規范請求),以向Java平台增添新的API和服務。JSR已成為Java界的一個重要標准。

 

2.Spring的配置文件

 默認情況下是applicationContext.xml文件。可以建很多XML文件,工程中一般都是這樣配置的。


 三:Spring基本功能及案例詳解

1.Spring的IOC

Spring內IOC的最直接體現就是@Autowired注解

而IOC的精髓就是解耦類中沒有顯式的對屬性的賦值代碼,同時屬性的實際類型和值在運行時有系統動態的賦值,Spring對IOC做了很大的擴展,使用者可以很靈活的控制注入的對象類型及值

SpringIOC(控制反轉):把對象的創建,初始化,銷毀等工作交給Spring容器來做。由Spring容器控制對象的生命周期。 

步驟:A:啟動Spring容器;B:從Spring容器中把對象取出來;C:最后,對象調用實際的業務方法。 

A:啟動Spring容器:

在類路徑下尋找配置文件來實例化容器:ApplicationContext context = new ClassPathXmlApplicationContext("配置文件類路徑");

通過這種方式加載。需要將spring配置文件放到當前項目的classpath路徑下。classpath路徑指的是當前項目的src目錄,該目錄是java源文件的存放位置。

 

在文件系統路徑下尋找配置文件來實例化容器:ApplicationContext context = new FileSystemXmlApplicationContext("配置文件系統路徑"); 

 

注:經常采用第一種方式啟動Spring容器。

B:從Spring容器中把對象取出來:

context.getBean("配置文件中bean的id"); 如:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");

C:對象調用實際的業務方法:

helloWorld.hello(); 

 


1.1.Spring容器創建對象的方式 

A:默認的情況下是調用該類默認的無參構造函數來創建類的對象。

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

  具體業務模塊配置文件applicationContext-creatobject.xml

業務類HelloWorld.java

 

客戶端代碼:

 

  由此看出:如果業務類HElloWorld.java又寫了該類的有參構造函數,此時就覆蓋了默認的無參構造函數。這樣就導致Spring容器在創建該類的對象時失敗。因為默認的是調用該類的默認無參構造函數,而此時又找不到無參構造函數了,所以就創建對象失敗。

 

B:Spring容器利用靜態工廠方法創建類對象。 

  案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

具體業務模塊配置文件applicationContext-creatobject-method.xml

 

業務類HelloWorld.java

 

靜態工廠類方法:

 

客戶端代碼:

 

C:Spring容器利用實例工廠方法創建對象

再次不做案例分析,記住即可。 

最后說明一下:spring配置文件中,只要是一個bean就會為該bean創建對象(默認是調用該類的默認構造函數創建對象)

 


1.2.Spring配置文件中別名的用

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-alias.xml

 

業務類HelloWorld.java

 

客戶端代碼:

 

由此看出:通過配置文件中的配置,可以達到在一個地方命名,在多個地方使用不同的名字的效果。


1.3.Spring容器創建對象的時機

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-creatobject-when.xml

業務類HelloWorld.java

 

客戶端代碼:

執行結果:

由執行結果可看出:在單例情況下(默認就是單例,關於單例,下面會講到):

A:在默認情況下,啟動spring容器的時候(ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml)),就調用該類的無參構造函數創建對象。所以spring容器創建對象的時機是:啟動spring容器時創建。 

B:在spring的配置文件bean中有一個屬性lazy-init="default/false/true":

a:如果lazy-init="default/false",在啟動spring容器的時候創建對象。

b:如果lazy-init="true",在獲取對象的時候創建對象,即context.getBean()時,創建對象。

a與b的意義:

在第一種情況下可以在啟動spring容器的時候,檢查spring配置文件的正確性。如果再結合tomcat,如果spring容器不能正常啟動整個tomcat就不能正常啟動。但是這樣的缺點是把一些bean過早的放在了內存中,如果有數據,則對內存來說是一個消耗。在第二種情況下,可以減少內存的消耗,但是不容易檢查出配置文件中的錯誤,排錯比較困難。 


1.4.Spring容器中bean的單例與多例

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-creatobject-scope.xml

 

業務類HelloWorld.java

 

客戶端代碼:

執行結果:

在配置文件的bean中的scope="singleton"的情況下(即默認情況下):

在配置文件的bean中的scope="prototype"的情況下:

從執行的結果,我們來總結歸納一下:

從第一個執行結果看出,由spring容器產生的bean默認是單例的。打印結果看出,兩次分別獲取的bean結果是一樣的。並且單例模式下,spring容器在啟動的時候創建對象。

從第二個執行結果看出,若果將配置文件中的bean的scope值修改為“prototype”,那么由spring容器產生的bean就是多例的。打印結果看出,兩次分別獲取的bean結果是不一樣的。並且在多例模式下,spring容器在context.getBean(),即獲取對象的時候創建對象。這里有兩次獲取bean,所以打印出兩個:new instance-----scope

綜上:可以在spring的配置文件 ,scope的值進行修改="singleton/prototype/request/session/global session/global" ,如果spring的配置文件的scope為“prototype”,則在得到或者說從spring容器獲取該bean的時候才創建對象。 


1.5.Spring容器中對象的生命周期

案例

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-initdestory.xml

業務類HelloWorld.java

客戶端代碼:

執行結果:

由執行結果的順序可以看出:在單例情況下,即默認scope="singleton"的時候

a:spring容器在啟動的時候創建對象;

b:spring容器執行init方法;

c:程序員調用自己的業務方法;

d:當spring容器關閉的時候執行destory方法。

spring容器:ApplicationContext applicationContext = new ClassPathXmlApplicationContext("");

它的關閉:需要將applicationContext轉化一下:

ClassPathXmlApplication cpxa = (ClassPathXmlApplicationContext) applicationContext; 

cpxa.close(); 這樣才能關閉spring容器,執行destory方法。

注意:當scope=“prototype”的時候(即多例的情況下),spring容器不會執行destory()方法。 




2.Spring的DI(依賴注入)

springDI:理解為依賴注入,俗稱給屬性賦值。

平常中,我們給類的屬性賦值,無非兩種方式:1.調用類的set,get方法;2.調用類的構造方法。比如下面一個類中的屬性類型,幾乎代表了所有類型:

public class Person{  

private Long pid;

private String pname;

private Student student;

private List lists;

private Set sets;

private Map map;

private Properties properties;

//set,get方法 

}

說明:一個類中的所有屬性都可以采用SpringDI的方式賦值,但並不是所有的屬性都適合賦值。

2.1.調用類的set,get方法

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

具體業務模塊配置文件applicationContext-di-set.xml

業務類Person.java

業務類Student.java

客戶端代碼:

執行結果:

總結:從業務中的標注看,

1.我這里使用了自己編寫的工具類SpringInit.java,是為了方便2的使用;

工具類的代碼如下:

public class SpringInit{

public static ApplicationContext context;//spring容器 

//靜態代碼塊,在類加載的之后執行,只執行一次

static{

context = new ClassPathXmlApplicationContext("applicationContext.xml");//啟動spring容器

 }

然后我的客戶端類繼承了這個工具類。

結合配置文件和執行結果,看出是通過set方法賦值的。首先創建對象解析所有的property,把name解析出來,拼接成set方法,把value和ref解析出來並賦值。 


2.2.調用類的構造方法

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-di-constructor.xml

業務類同1.1中的業務類相同,只是Person類中添加一個構造方法:

public Person(String pname,Student){

this.pname = pname;

this.student = student;

}

客戶端代碼:

執行結果:

總結:構造函數的方式賦值:

1.如果spring的配置文件中的bean中沒有<constructor-arg>元素,則spring容器調用默認的構造函數創建對象。
2.如果spring的配置文件中的bean中有<constructor-arg>元素,則該元素確定唯一的構造函數創建對象並賦值。
<constructor-arg>中的元素:index:代表參數的位置 從0開始計算。
type:值的是參數的類型。
value:給基本類型賦值。
ref:給引用類型賦值。

2.3.spring的IOC與DI的意義

案例:

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

具體業務模塊配置文件applicationContext-document.xml

業務類:

ducument接口:

三個實現接口的類:

------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------

文檔管理類DocumentManager.java

客戶端代碼:

 

執行結果:

從例子可以看出,Spring的IOC與DI的完美結合,是其做到了真正的面向接口編程。如果我們想讀寫Excel或者Word,只需要修改配置文件中的傳入參數即可。而傳統的方式是不完全面向接口的編程,把實現類暴露給客戶端了。


2.3.spring的IOC與DI實現mvc的模擬例子

案例:  

Spring的主配置文件:applicationContext.xml(因為我這里將會講到很多模塊,所以我用一個主配置文件去加載各個模塊的配置文件):

 

具體業務模塊配置文件applicationContext-mvc.xml

業務類:

服務層接口與實現:

-----------------------------------------------------------------------------------------------

dao層接口與實現:

------------------------------------------------------------------------------------------

控制層action

客戶端代碼:

執行結果:

從例子可以看出,Spring的IOC與DI的完美結合,是其做到了真正的面向接口編程。這里的依賴注入都采用了set的方式注入的。

 

參考http://www.cnblogs.com/vanl/p/5607534.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM