Spring的基本用法(大全)
Spring的簡介
基於依賴注入的核心機制、基於AOP的宣告式事務管理,與多種持久層技術的整合。使用Spring框架必須使用Spring Core Container只要由org.springframework.core、org.springframework.beans、org.springframework.context、org.springframework.expression四個包及其子包組成。
- 像大工廠一樣,負責建立、管理所有Java物件,這些Java物件就是Bean。
- 管理容器中Bean之間的依賴關係
- 本質是通過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的核心介面
ApplicationContext和BeanFactory,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)
注意事項
- 建立BeanFactory例項時,必須提供XML配置檔案作為引數,XML配置檔案通常使用Resource物件傳入。(Resource介面是Spring提供的資源訪問介面)
- 如果需要載入多個配置檔案來建立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等
- 訪問網路資源
- 訪問類載入路徑下的資源
- 訪問檔案系統資源
- 訪問應用相關資源
- 訪問位元組陣列資源
ApplicationContext中使用資源
1.使用ApplicationContext實現類指定訪問策略
- ClassPathXmlApplicationContext:對應使用ClassPathResource進行資源訪問
- FileSystemXmlApplicationContext:對應使用FileSystemResource進行資源訪問
- XmlWebApplicationContext:對應使用ServletContextResource進行資源訪問
2.使用字首指定訪問策略
http:、ftp:等字首,用來確定對應的資源訪問策略。
3.classpath*:字首用法