1. 程式人生 > >Spring的基本用法(大全)

Spring的基本用法(大全)

Spring的簡介

基於依賴注入的核心機制、基於AOP的宣告式事務管理,與多種持久層技術的整合。使用Spring框架必須使用Spring Core Container只要由org.springframework.core、org.springframework.beans、org.springframework.context、org.springframework.expression四個包及其子包組成。

  1. 像大工廠一樣,負責建立、管理所有Java物件,這些Java物件就是Bean。
  2. 管理容器中Bean之間的依賴關係
  3. 本質是通過XML配置檔案來驅動Java程式碼

使用Spring管理bean

Spring容器是一個工廠。

Bean是Spring容器管理的物件,一切Java物件都可以是Bean

bean與Java Bean的不同

  • 寫法不同:Java Bean必須遵守特定的規範,必須給每個屬性提供對應的getter和setter方法,而Bean只需提供setter方法。
  • 用處不同:Bean是Java例項、Java元件,JavaBean通常作為DTO(資料傳輸物件)來封裝值物件,來傳遞引數
  • 生命週期不同:JavaBean作為值物件傳遞,不接受任何容器管理其生命週期。Bean由Spring管理生命週期。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
 <!-- 配置db.properyies檔案位置 -->
    <bean id="configurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="locations" value="classpath:db.properties"></property>
    </bean>
</beans>

<bean/>驅動spring以反射方式呼叫該類無參的構造器。id為Bean的唯一標識,通過id屬性值訪問Bean和管理Bean之間的依賴。class指定Bean的實現類。

<property/>驅動spring在底層以反射執行setter方法賦值。 name屬性決定執行哪個setter方法,value或ref決定執行setter方法傳入的引數。ref可指定一個bean屬性,該屬性用於引用容器內中其他Bean例項的id屬性值。

<value><property/>的子元素相當於value,可指定呼叫setDriverClass()方法。的引數值為com.mysql.jdbc.Driver。設值注入。現在用得少。

 

程式通過Spring容器來訪問容器中的Bean,ApplicationContext是Spring容器最常用的介面,有如下兩種實現類:

  • ClassPathXmlApplicationContext:從類載入路徑下搜尋配置檔案,根據配置檔案建立Spring容器。通常用這個。
  • FileSystemXmlApplicationContext:從檔案系統的相對路徑
public class BeanTest
{
    public static void main(String[] args)throws Exception{
//  建立Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        // 獲取id為person的Bean
        Person p = ctx.getBean("person",Person.Class);
 
    }
}

Spring的核心機制:依賴注入(DI ,Dependency Injection)

依賴:A物件呼叫B物件的方法,即A物件依賴於B物件。

注入普通的屬性值,還可以注入其他Bean的引用。當某個Java例項需要其他Java例項時,系統自動提供所需例項,無需程式顯示獲取。

工廠模式和被依賴物件的介面耦合,被依賴物件交給工廠建立。

現在只需被動的等待Spring容器注入。

實現方法:

  • 設值注入。IOC(控制反轉)容器使用成員變數的setter方法來注入被依賴物件
  • 構造注入。IOC(控制反轉)容器使用構造器來注入被依賴物件

Spring推薦面向介面程式設計。不論呼叫者還是被依賴者都定義為介面。也可以通過註解,利用反射建立例項。

public class Chinese implements Person{
    private Axe axe;
//設值注入所需的setter方法
    public void setAxe(Axe axe){
        this.axe=axe;
    }
    public void useAxe(){
// 實現Person介面的useAxe方法
        System.out.println(axe.chop());
//呼叫chop方法,表明Person物件依賴於axe物件
    }
}

使用XML配置檔案指定例項之間的依賴關係。

構造注入

通俗來說,就是驅動Spring底層以反射方式執行帶指定引數的構造器。

問題:<bean/>總是驅動Spring執行無參的構造器來建立物件,怎麼驅動Spring執行有引數的構造器???

答案是<contructor-arg  />子元素。<contructor-arg  />子元素代表一個構造器引數。

public class Chinese implements Person{
    private Axe axe;
//構造注入所需的帶引數的構造器
    public Chinese(Axe axe){
        this.axe=axe;
    }
    public void useAxe(){
// 實現Person介面的useAxe方法
        System.out.println(axe.chop());
//呼叫chop方法,表明Person物件依賴於axe物件
    }
}

//對應的配置檔案新增<contructor-arg  />子元素

優先依賴的,優先注入。

建議:以設值注入為主,構造注入為輔。依賴關係無需變化的注入,就是用構造注入。

Spring的核心介面

ApplicationContextBeanFactory,ApplicationContext是BeanFactory的子介面

BeanFactory

方法

  • boolean containsBean(String name):
  • <T> T getBean(Class<T> requiredType)返回屬於requiredType型別的Bean例項。Object getBean(String name)容器id為name的Bean例項
  • Class<?> getType(String name)

注意事項

  1. 建立BeanFactory例項時,必須提供XML配置檔案作為引數,XML配置檔案通常使用Resource物件傳入。(Resource介面是Spring提供的資源訪問介面)
  2. 如果需要載入多個配置檔案來建立Spring容器,利用ApplicationContext來建立SessionFactory的例項。
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml","service.xml");

ApplicationContext

使用ApplicationContext例項作為容器,Spring的上下文。

允許以宣告式方式操作容器,除了提供BeanFactory所支援的全部功能外,還支援如下功能:

  • ApplicationContext預設會預初始化所有的singleton Bean,也可通過配置取消預初始化。不加特殊配置,Bean預設為singleton行為
  • ApplicationContext繼承MessageSource介面,提供國際化支援。
  • 資源訪問,如URL和檔案
  • 事件機制
  • 同時載入多個配置檔案
  • 以宣告式方式啟動建立Spring容器

優先使用ApplicationContext

<bean />元素指定lazy-init="true"阻止容器預初始化該Bean

ApplicationContext的國際化支援

ApplicationContext繼承MessageSource介面,提供國際化支援

String  getMessage(String code,Object[] args,Locale loc)

String getMessage(String code,Object[] args,Locale loc)

ApplicationContext的事件機制

ApplicationContext的事件機 制是觀察者設計模式實現。通過ApplicationEvent(容器事件)和ApplicationListener(監聽器)介面實現事件處理。

事件源、事件和事件監聽器組成

Spring容器中的Bean

  • 開發Bean
  • 配置Bean

Bean的基本定義和別名

<beans />元素是Spring的根元素,屬性如下:

  • default-merge:指定所有Bean預設的merge行為
  • default-lazy-init:指定所有Bean預設的延遲初始化
  • default-autowire:自動裝配行為。no、byName、byType、constructor、autodetect
  • default-autowire-candidates:指定所有Bean預設是否作為作為自動裝配的候選Bean。不做自動裝配設為false。
  • default-init-method:初始化方法
  • default-destroy-method:回收方法

定義Bean時,通常指定兩個屬性:

  • id:Bean的唯一標識
  • class:實現類
  • name:指定別名,多個別名可用逗號、冒號、空格
  • <alias />子元素為已有的Bean指定別名。name:指定Bean例項的標誌,alias:別名

容器中Bean的作用域

5種作用域:

  • singleton(常用):預設單例,整個Spring IOC容器中,singleton只生成一個bean例項
  • prototype(常用):每次通過容器的getBean()方法獲取prototype作用域的Bean,都將產生新的例項
  • request:對於一次HTTP請求,request作用域的Bean就只生成一個例項。Web應用中生效
  • session:對於一次HTTP會話,session作用域的Bean就只生成一個例項。Web應用中生效
  • global session:每個全域性的HTTP session對應一個作用域。僅在使用portlet context有效,Web應用中生效。

使用自動裝配注入合作者Bean

通過<bean />的autowire屬性指定或<beans />的default-autowire指定。屬性值如下:

  • no
  • byName:根據setter的方法名。沒找到匹配BeanSpring不做任何事情。 
  • byType:根據setter的方法引數型別。容器包含多於一個的匹配引數型別例項就會丟擲異常。
  • constructor:與byType相似,區別在於自動匹配構造器的引數。如果找不到匹配與構造器引數型別匹配的Bean就會丟擲錯誤
  • autodetect:Spring根據Bean內部結構,自行決定使用construct或byType策略。如果是預設建構函式就會使用byType。

注入巢狀Bean

如果某個Bean所依賴的Bean不想被Spring容器直接訪問,可以使用巢狀Bean。

巢狀Bean:把<bean />作為<property/>或<contructor-args/>的子元素,那麼該<bean/>元素配置的Bean僅僅作為setter注入、構造注入的引數。由於容器不能獲取巢狀Bean,所以不用指定id

本質上與使用ref引用容器中的另一個Bean一樣。

小貼士

  • 形參型別是基本型別、String、日期等,用value指定字面值即可。
  • 形參型別是複合類(如Person、Dog、DataSource等Java物件)作為實參。1.使用ref引用容器中已配置的Bean(Java物件)2.使用<bean/>元素配置巢狀Bean

注入集合值

在<property/>元素下新增<list/>、<set/>、<map/>和<props/>設定集合引數值

<property name="">
<list>
<!--每個value、ref、bean都配置List元素 -->
    <value>小學</value>
    <value>中學</value>
</list>
<property/>
<property name="">
<map>
    <entry key="" value=""/>
    <entry key="" value=""/>
</map>
<property/>
<property name="">
<map>
    <entry key="" value-ref=""/>
    <entry key="" value-ref=""/>
</map>
<property/>

<property name="">
    <props>
<!--每個key、value只能是字串 -->
        <prop key="屬性名"></prop>
        <prop key="血壓">125</prop>
        <prop key="身高">163</prop>
    <props/>
<property/>

<property name="">
<set>
<!--每個value、ref、bean都配置set元素 -->
    <value>普通字串</value>
    <bean class="類的路徑" />
    <ref bean="類名" />
    <list>
        <value></value>
        <set>
            <value type="int"></value>
        </set>
    </list>
</set>
<property/>

組合屬性

除最後一個屬性外,其他屬性不能為null

 

Java配置管理

Java配置類的三個Annotation

  • @Configuration:用於修飾配置類
  • @Bean:修飾一個方法,將該方法的返回值定義成容器中的一個Bean
  • @Value:修飾Field,為該Field配置一個值
  • @Import:修飾Java配置類,用於向當前Java配置類中匯入其他Java配置類
  • @Scope:修飾一個方法,方法對應的Bean的作用域
  • @Lazy:修飾一個方法,方法對應的Bean是否延遲初始化
  • @DependsOn:修飾一個方法,指定在初始化該方法對應的Bean及其依賴關係之前初始化指定的Bean。

以XML配置方式為主,需要在XML配置中載入Java類配置

<!-- 載入Java配置類 -->
<bean class="org.crazyit.app.config.AppConfig">

以Java類配置為主,藉助@ImportResources註解修飾Java配置類

@Configuration
// 匯入XML配置
@ImportResources("classpath:/beans.xml")

建立Bean的3種方式

  • 呼叫構造器建立Bean
  • 呼叫靜態工廠方法建立Bean
  • 呼叫例項工廠方法建立Bean

呼叫構造器建立Bean

如果不採用構造注入,Spring底層預設呼叫Bean類的無參構造器建立例項。所有基本型別初始化為0或false,所有引用型別初始化為null。根據配置檔案例項化被依賴的Bean,為Bean注入依賴關係,最後將一個完整的Bean例項返回程式。

呼叫靜態工廠方法建立Bean

<bean />必須指定class屬性。此時class指定的是靜態工廠類。還需要使用factory-method屬性指定靜態工廠方法。Spring呼叫靜態工廠方法返回Bean例項。

public class BeingFactory{
    //返回Being例項的靜態工廠方法
    //	引數arg決定返回哪個Being類的例項
	public static Being getBeing(String arg){
		if(arg.equalsIgnoreCase("dog")){
			return new Dog();
//			返回Dog例項
		}
//		否則返回Cat例項
		else{
			return new Cat();
		}
	}
}
<bean class="BeanFactory" factory-method="getBeing">
<!-- 配置靜態工廠方法的引數 -->
<constructor-arg value="dog"/>
<property name="msg" value="the dog"/>
</bean>

呼叫例項工廠方法建立Bean

例項工廠和靜態工廠只有一點不同:呼叫靜態工廠方法只需使用工廠類,而呼叫例項工廠需要工廠例項。

配置靜態工廠方法使用class指定靜態工廠類,配置例項工廠使用factory-bean指定工廠例項。

使用例項工廠時,<bean/>無須class屬性,Spring容器呼叫例項工廠的工廠方法建立Bean例項。

例項工廠方法建立<bean/>元素時需要指定的屬性:

  • factory-bean:指定工廠Bean的id
  • factory-method:指定例項工廠的工廠方法

抽象Bean與子Bean

<bean/>元素下新增abstract="true",不指定class就是抽象Bean,不能被例項化,只能被繼承

<bean/>元素下新增parent="父Bean的id",該bean是一個子bean.

Bean繼承和Java繼承的區別

  • Spring中子Bean與父Bean可以是不同型別,Java繼承保證子類是特殊父類
  • Bean的繼承是例項間的關係,主要表現在引數值的延續。Java繼承是類之間的關係,主要表現在方法、屬性的延續。
  • 子Bean不能作為父Bean使用,不具備多型性,Java繼承子類例項可以當父類例項使用

工廠Bean:與前面不同,Spring的一種特殊Bean,必須實現FactoryBean介面。返回該Bean例項的getObject()方法的返回值。開發者實現getObject()方法。(返回某個型別的值)

容器中Bean的生命週期

Spring可以管理singleton作用域的Bean的生命週期,Spring可以精確的知道該Bean何時被建立、初始化完成、何時準備銷燬該例項。

prototype作用域的Bean,Spring僅僅負責建立。其他就交給客戶端程式碼管理,無法管理。

注入依賴關係之後

  • 使用init-method屬性:指定某個方法在Bean注入依賴關係之後自動執行
  • InitializingBean介面:在為Bean注入依賴關係之後實現void afterPropertiesSet() throws Exception

Bean銷燬之前

  • 使用destroy-method屬性:指定某個方法在Bean銷燬之前自動執行
  • 實現disposableBean介面:void destroy() throws Exception

獲取其他Bean的屬性值

PropertyPathFactoryBean用來獲取其他Bean的屬性值。(實際上就是getter方法的返回值)

  • 呼叫哪個物件:由PropertyPathFactoryBean的setTargetObject(Object targetObject)方法指定
  • 呼叫哪個getter方法:由PropertyPathFactoryBean的setPropertyPath(String propertyPath)方法指定。
<bean class="" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="person"/>
<property name="propertyPath" value="son"/>
</bean>

<util:property-path/>作為PropertyPathFactoryBean簡化配置。id屬性:指定getter方法的返回值定義成名為id的Bean例項。path:指定哪個Bean例項、哪個屬性暴露出來。

獲取Field值

通過FieldRetrievingFactoryBean類,可訪問類的靜態Field或物件的例項Field值。可將獲取的值注入到其他Bean,也可直接定義新的Bean。<util:constant/>

<bean class="" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetClass" value="java.sql.Connection"/>
<property name="targetField" value="TRANSACTION_SERIALIZABLE"/>
</bean>

獲取方法返回值

通過MethodInvokingFactoryBean工廠Bean,可以獲取任意類的類方法。

SpEL

Spring表示式語言即SpEL。略

Spring的零配置支援

  • @Component:標註普通Java Bean類,首字母小寫,其他不變
  • @Controller:控制器元件類
  • @Service:業務邏輯元件類
  • @Repository:DAO元件類
  • @Scope:作用域
  • @Resource(name=" ")和<property/>的ref效果相同,可以省略name。修飾setter方法或例項變數
  • @PostConstruct修飾的方法是Bean建立之後執行方法
  • @PreDestroy修飾的方法是Bean銷燬之前執行方法
  • @DependsOn:強制初始化其他Bean
  • @Lazy:指定Bean是否取消預初始化。延遲。
  • @Autowired:自動裝配,可以修飾setter方法、普通方法、例項變數和構造器。預設採用byType自動裝配策略
  • @Qualifier:根據Bean的id執行自動裝配

 

自動掃描指定包及其子包下的所有Bean類<context:component-scan base-package="org.crazyit.app.service"/>

<context:component-scan base-package="org.crazyit.app.service">
    <context:include-filter type="regex" expression=".*Chinese"/>
    <context:include-filter type="regex" expression=".*Axe"/>
</context:component-scan>

<context:exclude-filter>或<context:include-filter>子元素指定Spring Bean類,只要位於指定路徑下的Java類滿足這個規則,就會當成Bean類處理。

type:指定過濾器型別

expression:過濾器所需要的表示式

Spring內建支援的4種過濾器:annotation(annotation過濾器)、assignable(類名過濾器)、regex(正則表示式)、aspectj(aspectj過濾器)

 

資源訪問

資源=>XML配置檔案、二進位制流等各種型別檔案

Resource介面的實現類有UrlResource等

  1. 訪問網路資源
  2. 訪問類載入路徑下的資源
  3. 訪問檔案系統資源
  4. 訪問應用相關資源
  5. 訪問位元組陣列資源

ApplicationContext中使用資源

1.使用ApplicationContext實現類指定訪問策略

  • ClassPathXmlApplicationContext:對應使用ClassPathResource進行資源訪問
  • FileSystemXmlApplicationContext:對應使用FileSystemResource進行資源訪問
  • XmlWebApplicationContext:對應使用ServletContextResource進行資源訪問

2.使用字首指定訪問策略

http:、ftp:等字首,用來確定對應的資源訪問策略。

3.classpath*:字首用法