1 Spring基本特徵
Spring是一個非常活躍的開源架構;它是一個基於Core來構架多層JavaEE系統的架構,它的主要目地是簡化企業開發.
Spring以一種非侵入式的方式來管理你的代碼,Spring提倡”最少侵入”,這也就意味著你可以適當的時候安裝或卸載Spring,Spring讓java亮了。 (開放–閉合原理),這裡是閉原則。
2 開發spring所需要的工具
(這裡先將spring2.5 ,後面3.0)
2.1 Spring的jar包
到http://www.springsource.org/download下載spring,然後進行解壓縮,在解壓目錄中找到下面jar檔案,拷貝到類路徑下
—spring的核心類庫 在spring文檔的dist下 dist\spring.jar
—引入的第三方類庫 都spring文檔的lib下,lib\jakarta-commons\commons-logging.jar
—如果使用了切面編程(AOP),還需要下列jar檔案 lib/aspectj/aspectjweaver.jar和aspectjrt.jarlib/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.2 Spring設定檔
預設情況下是applicationContext.xml檔案。可以建立很多xml檔案,工程中一般都是這樣配置的。(src目錄下建)
3 Spring準系統詳解
3.1 SpringIOC
Spring的控制反轉:把對象的建立、初始化、銷毀等工作交給spring容器來做。由spring容器控制對象的生命週期。
步驟:
•A. 啟動spring容器
1、 在類路徑下尋找設定檔來執行個體化容器
複製代碼 代碼如下:
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
可以在整個類路徑中尋找xml檔案
* 通過這種方式載入。需要將spring的設定檔放到當前項目的classpath路徑下
* classpath路徑指的是當前項目的src目錄,該目錄是java源檔案的存放位置。
2、 在檔案系統路徑下尋找設定檔來執行個體化容器
Spring的設定檔可以指定多個,可以通過String數組傳入。
註:經常用第一種方法啟動容器
•B. 從spring容器中提取對象
spring 容器結構:
3.2 別名
<beans> <alias name="person" alias="p"/>//alias這裡是別名,可以通過p,得到person這個bean. <bean name="person" class="cn.itcast.aliasspring.Person"/></beans>
通過這樣的配置,可以達到在一個地方命名,在多個地方使用不同的名字的效果。
3.3 Spring容器內部對象
1 建立對象的方式
1.1 無參建構函式
<bean id="helloWorld" class="com.itheima10.spring.createobject.HelloWorld"></bean>
1.2 靜態Factory 方法
<bean id="helloWorld2" class="com.itheima10.spring.createobject.method.HelloWorldFactory"
factory-method="getInstance"></bean>
1.3 執行個體Factory 方法
<bean id="helloWorldFactory" class="com.itheima10.spring.createobject.method.HelloWorldFactory2"></bean>
<bean id="helloWorld3" factory-bean="helloWorldFactory" factory-method="getInstance"></bean>
記住概念即可,用的最多的是第一種方法,但是和別的工具整合時,用的是執行個體原廠模式。
執行個體:
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 把一個類放入到spring容器中,該類就稱為一個bean --> <!-- bean描述了一個類 id 唯一的標示 class 類的全名 --> <bean id="helloWorld" class="com.itheima10.spring.createobject.HelloWorld"></bean> <!-----------------------別名--------------------------------------> <!-- name的屬性和bean的id匹配 alias 別名 --> <alias name="helloWorld" alias="狗蛋"/> <alias name="helloWorld" alias="習近平"/><!-----------------------靜態Factory 方法--------------------------------------><!-- 把helloWorldFactory放入到spring容器中 factory-method Factory 方法 --> <bean id="helloWorld2" factory-method="getInstance" class="com.itheima10.spring.createobject.method.HelloWorldFactory"></bean><!-----------------------執行個體Factory 方法--------------------------------------> <!-- 把helloWorldFactory2放入到spring容器中 factory-bean 指明了工廠bean factory-method 指明了該工廠bean中的方法 --> <bean id="helloWorldFactory" class="com.itheima10.spring.createobject.method.HelloWorldFactory2"></bean> <bean id="helloWorld3" factory-bean="helloWorldFactory" factory-method="getInstance"></bean></beans>
建立實體類HelloWorld
package com.itheima10.spring.createobject;public class HelloWorld { public void hello(){ System.out.println("hello"); }}
建立靜態工廠HelloWorldFactory
package com.itheima10.spring.createobject.method;public class HelloWorldFactory { public static HelloWorld getInstance(){ System.out.println("static method"); return new HelloWorld(); }}
建立實體工廠HelloWorldFactory2
package com.itheima10.spring.createobject.method;public class HelloWorldFactory2 { /** * 必須先建立工廠對象,才能調用該方法 * @return */ public HelloWorld getInstance(){ return new HelloWorld(); }}
編寫測試方法CreateObjectMethodTest
package com.itheima10.spring.createobject.method;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * 第二種和第三種產生方式能看明白就OK了 * @author zd * */public class CreateObjectMethodTest { /** * 在預設情況下,spring容器調用的是一個類的預設的建構函式建立對象 */ @Test public void testCreateObject_Default(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld"); helloWorld.hello(); } /** * 利用靜態工廠建立對象 * <bean id="helloWorld2" factory-method="getInstance" class="com.itheima10.spring.createobject.method.HelloWorldFactory"></bean> spring容器做的事情: 利用HelloWorldFactory類調用了getInstance方法 */ @Test public void testCreateObject_StaticFactory(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld2"); helloWorld.hello(); } /** * 執行個體Factory 方法建立對象 * <bean id="helloWorldFactory" * class="com.itheima10.spring.createobject.method.HelloWorldFactory2"></bean> * <bean id="helloWorld3" factory-bean="helloWorldFactory" factory-method="getInstance"></bean> spring容器內部做的事情: 1、建立一個helloWorldFactory對象 2、由該對象調用getInstance產生helloWorld對象 */ @Test public void testCreateObject_InstanceFactory(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld3"); helloWorld.hello(); }}
2 對象的scope
對象的scope有兩個屬性:singleton 與prototype。singleton表示單例
2.1 singleton(預設值)
在每個Spring IoC容器中一個bean定義只有一個對象執行個體(共用)。
2.2 prototype
允許bean可以被多次執行個體化(使用一次就建立一個執行個體) . Spring不能對一個prototype bean的整個生命週期負責.這就意味著清楚prototype範圍的對象並釋放任何prototype bean所持有的昂貴資源都是用戶端的責任。
<bean id="helloWorld" class="com.itheima10.spring.scope.HelloWorld" scope="singleton"></bean>
<bean id="helloWorld" class="com.itheima10.spring.scope.HelloWorld" scope="prototype"></bean>
建立HelloWorld類
public class HelloWorld { public List<String> lists = new ArrayList<String>(); public HelloWorld(){ System.out.println("new instance"); } public void hello(){ System.out.println("hello"); }}
建立測試類別ScopeTest
package com.itheima10.spring.scope;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class ScopeTest { /** * 把一個bean放入到spring容器中,預設的是單例 * 如果一個類放入到spring容易中,而這個類是單例的,那麼該類中的屬性將會成為共用的 */ @Test public void testCreateObject_Scope_Default(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld hello1 = (HelloWorld)context.getBean("helloWorld"); hello1.lists.add("aaaa"); hello2= (HelloWorld)context.getBean("helloWorld"); hello2.lists.add("bbbb"); System.out.println(helloWorld.lists.size());//2,並且只輸出一次new instance } /** * 如果spring的設定檔如下: * <bean id="helloWorld" class="com.itheima10.spring.scope.HelloWorld" scope="prototype"></bean> 那麼spring容器會為建立多個對象 */ @Test public void testCreateObject_Scope_Prototype(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld hello1 = (HelloWorld)context.getBean("helloWorld"); hello1.lists.add("aaaa"); hello2= (HelloWorld)context.getBean("helloWorld"); hello2.lists.add("bbbb"); System.out.println(helloWorld.lists.size());//1,並且只輸出兩次new instance }}
3 初始化bean時機
懶載入——預設情況下會在容器啟動時初始化bean,但我們可以指定Bean節點的lazy-init=“true”來延遲初始化bean,這時候,只有第一次擷取bean會才初始化bean。如:
<bean id="xxx" class="cn.itcast.OrderServiceBean" lazy-init="true"/>
如果想對所有bean都應用延遲初始化,可以在根節點beans設定default-lazy-init=“true“,如下:
<beans default-lazy-init="true“ ...>
Spring預設在啟動時將所有singleton bean提前進行執行個體化。提前執行個體化意味著作為初始化的一部分,ApplicationContext會自動建立並配置所有的singleton bean.通常情況下這是件好事。因為這樣在配置中有任何錯誤能立即發現。
Lazy-init 為false,spring容器將在啟動的時候報錯(比較好的一種方式)
Lazy-init 為true,spring容器將在調用該類的時候出錯。
配置applicationContext.xml
<bean id="helloWorld" class="com.itheima10.spring.createobject.when.HelloWorld" scope="prototype"></bean></beans>
建立測試類別CreateObjectWhenTest
package com.itheima10.spring.createobject.when;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class CreateObjectWhenTest { /** * 預設情況下的順序 * 1、啟動spring容器 * 2、建立HelloWorld對象 * 3、對象調用方法 * * <bean id="helloWorld" class="com.itheima10.spring.createobject.when.HelloWorld"></bean> <bean id="helloWorld2" class="com.itheima10.spring.createobject.when.HelloWorld"></bean> 因為在spring容器中聲明了兩個bean,所以spring容器要建立兩個對象 說明: 如果struts2,hibernate,spring容器整合,如果spring的設定檔中出現錯誤 當 tomcat容器啟動的時候,就會報錯,錯誤會特別早的顯示出來 如果一個bean存放了大量的資料,這種方式不好,有可能會把資料過早的停留在記憶體中 如果一個bean不是單例,那麼不管怎麼樣配置,都在是context.getBean時才要建立對象 */ @Test public void testCreateObject_When_Default(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); context.getBean("helloWorld"); } /** * <bean id="helloWorld" class="com.itheima10.spring.createobject.when.HelloWorld" lazy-init="true"></bean> * 順序 * 1、啟動spring容器 * 2、context.getBean * 3、調用構造器函數建立對象 * 說明: 如果struts2,hibernate,spring容器整合,如果spring的設定檔中出現錯誤 只有當用到該bean的時候才會報錯。 如果一個bean存放了大量的資料,需要的時候才要載入資料 */ @Test public void testCreateObject_When_Lazy(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); context.getBean("helloWorld"); }}
4 init、destroy方法
Spring初始化bean或銷毀bean時,有時需要作一些處理工作,因此spring可以在建立和拆卸bean的時候調用bean的兩個生命週期方法。可以指定方法進行操作。
<bean id=“foo” class=“...Foo” init-method=“setup” destory-method=“teardown”/>
當foo被載入到Spring容器中時調用init-method方法。當foo從容器中刪除時調用destory-method(scope = singleton有效)
編寫HelloWorld
public class HelloWorld { public HelloWorld(){ System.out.println("new instance"); } public void init(){ System.out.println("init"); } public void destroy(){ System.out.println("destroy"); } public void hello(){ System.out.println("hello"); }}
編寫測試類別InitDestroyTest
package com.itheima10.spring.ioc.initdestroy;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class InitDestroyTest { /** * init-method="init" * 執行順序: * 1、啟動spring容器 * 2、建立helloWorld對象 * 3、執行init方法 * spring容器內部自動執行的 * 4、對象調用方法 * 5、只有當spring容器關閉掉的情況下才能執行destroy方法 前提條件:bean是單例的 * 該方法也是由spring容器內部調用的 * 說明: * 如果一個bean不是單例的,則spring容器不負責對象的銷毀。 * 在spring容器中,只有一個bean是單例的情況下,spring容器才要負責對象的建立、初始化、銷毀工作 * 如果一個bean不是單例,spring容器只負責建立、初始化 */ @Test public void testInitDestroy(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld"); helloWorld.hello(); ClassPathXmlApplicationContext applicationContext = (ClassPathXmlApplicationContext)context; applicationContext.close(); }}
執行順序圖:
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。