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"/></beans>
通過這樣的配置,可以達到在一個地方命名,在多個地方使用不同的名字的效果。
3.3 Spring容器內部對象
1 創建對象的方式
1.1 無參構造函數
<bean id="helloWorld"></bean>
1.2 靜態工廠方法
<bean id="helloWorld2"
factory-method="getInstance"></bean>
1.3 實例工廠方法
<bean id="helloWorldFactory"></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"></bean> <!-----------------------別名--------------------------------------> <!-- name的屬性和bean的id匹配alias 別名--> <alias name="helloWorld" alias="狗蛋"/> <alias name="helloWorld" alias="習近平"/><!-----------------------靜態工廠方法--------------------------------------><!-- 把helloWorldFactory放入到spring容器中factory-method 工廠方法--> <bean id="helloWorld2" factory-method="getInstance" ></bean><!-----------------------實例工廠方法--------------------------------------> <!-- 把helloWorldFactory2放入到spring容器中factory-bean 指明了工廠bean factory-method 指明了該工廠bean中的方法--> <bean id="helloWorldFactory"></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" ></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" *></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" scope="singleton"></bean>
<bean id="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" 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" 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" 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"></bean> <bean id="helloWorld2"></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" 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(); }}執行順序圖:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。