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、 在類路徑下尋找配置文件來實例化容器
可以在整個類路徑中尋找xml文件
* 通過這種方式加載。需要將spring的配置文件放到當前項目的classpath路徑下
* classpath路徑指的是當前項目的src目錄,該目錄是java源文件的存放位置。
2、 在文件系統路徑下尋找配置文件來實例化容器
Spring的配置文件可以指定多個,可以通過String數組傳入。
注:經常用第一種方法啟動容器
•B. 從spring容器中提取對象
spring 容器結構:
3.2 別名
1
2
3
4
|
<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 靜態工廠方法
<bean id="helloWorld2" class="com.itheima10.spring.createobject.method.HelloWorldFactory"
factory-method="getInstance"></bean>
1.3 實例工廠方法
<bean id="helloWorldFactory" class="com.itheima10.spring.createobject.method.HelloWorldFactory2"></bean>
<bean id="helloWorld3" factory-bean="helloWorldFactory" factory-method="getInstance"></bean>
記住概念即可,用的最多的是第一種方法,但是和別的工具集成時,用的是實例工廠模式。
實例:
配置applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<? 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 = "習近平" /> <!-----------------------靜態工廠方法--------------------------------------> <!-- 把helloWorldFactory放入到spring容器中 factory-method 工廠方法 --> < bean id = "helloWorld2" factory-method = "getInstance" class = "com.itheima10.spring.createobject.method.HelloWorldFactory" ></ bean > <!-----------------------實例工廠方法--------------------------------------> <!-- 把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
1
2
3
4
5
6
7
|
package com.itheima10.spring.createobject; public class HelloWorld { public void hello(){ System.out.println( "hello" ); } } |
建立靜態工廠HelloWorldFactory
1
2
3
4
5
6
7
8
|
package com.itheima10.spring.createobject.method; public class HelloWorldFactory { public static HelloWorld getInstance(){ System.out.println( "static method" ); return new HelloWorld(); } } |
建立實體工廠HelloWorldFactory2
1
2
3
4
5
6
7
8
9
10
11
|
package com.itheima10.spring.createobject.method; public class HelloWorldFactory2 { /** * 必須先創建工廠對象,才能調用該方法 * @return */ public HelloWorld getInstance(){ return new HelloWorld(); } } |
編寫測試方法CreateObjectMethodTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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(); } /** * 實例工廠方法創建對象 * <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類
1
2
3
4
5
6
7
8
9
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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
1
2
3
4
|
< bean id = "helloWorld" class = "com.itheima10.spring.createobject.when.HelloWorld" scope = "prototype" ></ bean > </ beans > |
建立測試類CreateObjectWhenTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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(); } } |
執行順序圖:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/i10630226/article/details/50502167