Spring簡介:
Spring是一個IOC(DI)和AOP容器框架:
- 輕量級:Spring是非侵入性的,基于開發(fā)的應用中的對象可以不依賴與Spring的API
- 依賴注入(DI - Dependency injection、IOC)
- 面向切面編程(AOP - aspect oriented programming)
- 容器:Spring是一個容器,因為其包含并且管理應用對象的生命周期
- 框架:Spring實現了使用簡單的組建配置組合成一個復雜的應用,在Spring中可以使用XML和Java注解組合這些對象
- 一站式:在IOC和AOP的基礎上可以整個各種企業(yè)應用的開源框架和優(yōu)秀的第三方類庫(Spring自身提供了展現層SpringMVC與持久層Spring JDBC)
Spring模塊:
Spring
搭建Spring開發(fā)環(huán)境:
- 導入jar包:
commons-logging.jar(Spring依賴的jar包)
spring-beans.RELEASE.jar
spring-context-RELEASE.jar
spring-core.RELEASE.jar
spring-expression.RELEASE.jar
spring-aop.RELEASE.jar
- Spring的配置文件:一個典型的spring文件項目需要創(chuàng)建一個或多個Bean配置文件,這些配置文件用于在SpringIOC容器里配置Bean.Bean的配置文件可以放在classpath下,也可以放在其他目錄下
Spring的設置基本步驟:
- 類路徑下創(chuàng)建配置文件:applicationContext.xml(配置bean)
<bean id="customer" class="com.djh.demo.Customer">
<property name="cusName" value="Tom"></property>
</bean>
- 在java Code中加入以下步驟注入bean:
- 創(chuàng)建Spring的IOC的容器對象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- 從IOC容器中獲取Bean的實例
Customer customer = ctx.getBean("customer");
Spring Bean的配置
- 配置形式:
- 基于XML文件的方式
- 基于注解的方式
- Bean的配置方式:
- 通過全類名(反射)
- 通過工廠方法(靜態(tài)工廠方法&實例工廠方法)
- FactoryBean
- IOC容器BeanFactory & ApplicationContext概述
- 依賴注入的方式:
- 屬性注入
- 構造器注入
- 注入屬性值細節(jié)
- 自動專配
- bean之間的關系:
- 繼承
- 依賴
- bean的作用域:
- singleton
- prototype
- WEB環(huán)境作用域
- 使用外部屬性文件
- 在Spring的IOC容器里配置Bean:
- 在xml文件中通過bean節(jié)點來配置bean
<bean id="customer" class="com.djh.demo.Customer"> <property name="cusName" value="Tom"></property> </bean>
- id:Bean的名稱
- 在IOC容器中必須是唯一的
- 若id沒有指定, Spring自動將權限定性類名作為Bean的名字
- id可以指定多個名字,之間用逗號拗引、分號或空格分隔
- Spring提供的兩種類型的IOC容器實現:
-
BeanFactory
:IOC容器的基本實現 -
ApplicationContext
:提供了更多的高級特性,為BeanFactory的子接口
-
- ApplicationContext的主要實現類:
- ClassPathXmlApplicationContext:從類路徑下加載配置文件
- FileSystemXmlApplicationContext:從文件系統(tǒng)中加載配置文件
- ApplicationContext在初始化上下文時就實例化所有單例的Bean
- 依賴注入的方式(3種):
- 屬性注入(即setter方法)借宵,屬性注入使用<property>元素,使用name屬性執(zhí)行Bean的屬性名稱,value屬性或<value>子節(jié)點指定屬性值
如:
- 屬性注入(即setter方法)借宵,屬性注入使用<property>元素,使用name屬性執(zhí)行Bean的屬性名稱,value屬性或<value>子節(jié)點指定屬性值
<bean id="customer" class="com.djh.demo.Customer">
<property name="cusName" value="Tom"></property>
</bean>
- 構造器注入
在<constructor-arg>元素里聲明,<constructor-arg>中沒有name屬性
<bean id="customer" class="com.djh.demo.Customer">
<!-- index參數決定Bean的構造方法中第幾個參數,type決定其參數類型 -->
<constructor-arg value="Tom" index="0" type="java.lang.String"></constructor-arg>
</bean>
- 工廠方法注入
對于注入的值包含特殊字符,如:<, >等,需要使用<![CDTAT[xxx]]>來表示 - 引用其他的Bean:
在Bean的配置文件中,可以通過<ref>元素或ref屬性為Bean的屬性或構造器參數指定對Bean的作用
也可以在屬性或構造器里包含Bean的聲明,這樣的Bean稱為內部Bean,不能被外部引用- 注入null值與級聯屬性:
可以使用<null/>元素標簽為Bean的字符串或其他對象類型的屬性注入null值
- 注入null值與級聯屬性:
- SSH均支持級聯屬性的配置,如:
<property name="customer.cusName" value="Michael" />
對于集合類型的屬性,使用list、set或map標簽方式,如下:
<property name="customers">
<list>
<ref bean="customer1" /> //或<value>Jacky</value>
<ref bean="customer2" />
</list>
</property>
<map>標簽里可以有多個<entry>子標簽,每個條目包含一個key與value,簡單常量使用key與value來定義,Nean引用通過key-ref與value-ref屬性定義
使用<props>定義java.util.Properties,該標簽使用多個<prop>作為子標簽,每個<prop>標簽必須定義key屬性
Spring自動裝配:
- Spring IOC容器可以自動裝配Bean,需要做的僅僅是在<bean>的autowire屬性里指定自動裝配的模式
- byType(根據類型自動裝配):Spring IOC 容器中不能有多個與目標Bean類型一致的Bean
- byName(根據名稱自動裝配):必須將目標Bean的名稱和屬性名設置的完全相同
- Bean的名稱與setter方法的名稱一致的矾削,如:
- Person Bean:
class Person{
private String personName;
private Address address;
//Getter and Setter method
}
- Address Bean:
class Address{
private String street;
//Getter and Setter method
}
- configure file:
<bean id="address" class="com.djh.demo.Address">
<property name="street" value="TianHe" />
</bean>
<bean id="person" class="com.djh.demo.Person" autowire="byType">
<property name="personName" value="Michael" />
</bean>
constructor(通過構造器自動裝配)
- Spring的Bean之間的關系:
- 繼承(parent屬性),如:
Customer{String:custName, int:age}
<bean id="customer" class="com.djh.demo.Customer"> <property name="age" value="20" /> <property name="custName" value="Lucy" /> </bean> <bean id="customer2" parent="customer"> <property name="custName" value="Michael" /> </bean>
- 依賴(depends-on屬性)
Spring允許通過depeds-on屬性設定Bean前置依賴的Bean,前置依賴的Bean會在本Bean實例化之前創(chuàng)建好
如果前置依賴于多個Bean,則可以通過逗號壤玫、空格的方式配置Bean的名稱
- 繼承(parent屬性),如:
- Spring中Bean的作用域,使用scope屬性進行配置哼凯,作用域有以下四個,默認為singleton
-
prototype
:容器初始化時不會創(chuàng)建Bean實例,而是在每次請求創(chuàng)建Bean的實例時返回 request
session
-
singleton
:創(chuàng)建IOC容器(ApplicationContext)時就創(chuàng)建了Bean實例,單例的 - 如:
-
<bean id="customer" class="com.djh.demo.Customer" scope="prototype">
<property name="custName" value="djh" />
</bean>
- 使用外部屬性文件:
Spring提供了一個PropertyPlaceholderConfigurer的BeanFactory后置處理器,該處理器允許用戶將Bean的部分內容移到屬性文件中,可以在Bean配置文件中使用形式為${var}
的變量,PropertyPlaceholderConfigurer從屬性文件里加載屬性,并使用這些屬性來替換變量
Spring還允許在屬性文件中使用${propName}
欲间,以實現屬性之間的相互引用 - 注冊PropertyPlaceholderConfigurer
- Spring2.0:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties" />
</bean>
- Spring2.5:
通過<context:property-placeholder>
元素
<beans>中添加context Schema定義,即加入context的Namespaces
在配置文件中加入如下配置:
//導入配置文件
<context:property-placeholder location="classpath:database.properties" />
//導入后可以使用${key}的形式訪問配置文件中對應的value
SpEL
- 一個支持運行時查詢和操作對象的表達式語言
語法類似于EL,使用#{xxx}
作為定界符,所有在大括號中的字符都被認為是SpEL - SpEL為bean的屬性進行動態(tài)復制提供了便利
- SpEL可以實現如下功能:
- 通過bean的id對bean進行引用
- 調用方法以及引用對象中的屬性
- 計算表達式的值
- 正則表達式的匹配
- SpEL字面量:
- 整數:
<property name="count" value="#{5}" />
- 小數:
<property name="frequency" value="#{88.2}" />
- 科學計數法:
<property name="capacity" value="#{1e4}" />
- String可以使用單引號或者雙引號作為字符串的定界符:
<property name="name" value="#{'djh'}" /> <property name="count" value='#{"Lucy"}' />
- Boolean:
<property name="display" value="#{true}" />
- 整數:
- SpEL引用Bean、屬性與方法:
- 引起其他對象(Bean):
<!-- 通過value屬性與SpEL配置的ean之間的應用關系 --> <property name="prefix" value="#{prefixGenerator}" />
- 引用其他對象的屬性:
<property name="stuffix" value="#{prefixGenerator.stuffix}" />
- 通過其他方法,還可以鏈式操作:
<!-- 通過value屬性和SpEL配置stuffix屬性值為另一個Bean的方法的返回值 --> <property name="stuffix" value="#{prefixGenerator.toString()}" /> <!-- 方法的連綴 --> <property name="stuffix" value="#{prefixGenerator.toString().toUpperCase()}" />
- 調用靜態(tài)方法或靜態(tài)屬性:通過T()調用一個類的靜態(tài)方法,返回一個類對象
<property name="initValue" value="#{T(java.lang.Math).PI}" />
Spring工廠方法配置Bean
- 調用靜態(tài)工廠方法創(chuàng)建Bean是將對象創(chuàng)建的過程封裝到靜態(tài)方法中
- 要聲明通過靜態(tài)方法創(chuàng)建的Bean,需要在Bean的class屬性里指定擁有該工廠方法的類,同時在
factory-method
屬性里指定工廠方法的名稱,最后使用<constructor-arg>
元素為該方法傳遞方法參數-
FactoryBean
(接口): -
getObject()
:返回bean對象 -
getObjectType()
:返回bean的類型 -
isSingleton()
:返回bean是否單例
-
注解配置Bean:
- 在classpath中掃描組件
Spring能夠從classpath下自動掃描,偵測和實例化具有特定注解的組件 - 特定組件包括以下幾個:
-
@Component
:基本注解,標識了一個受Spring管理的組件 -
@Repository
:標識持久層組件 -
@Service
:標識服務層(業(yè)務層)組件 -
@Controller
:標識表現層組件
-
- 對于掃描到的組件,Spring有默認的命名策略,使用非限定類名,第一個字母小寫,也可以在注解中通過value屬性值標識組件的名稱
- 當在組件類上使用了特定的注解之后,還需要在Spring的配置文件中聲明
<context:component-scan>
:
base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包里及其子包中的所有類 - 當需要掃描多個包時,可以使用逗號分隔
- 如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,如:
<context:component-scan
base-package="com.djh.demo.spring.beans"
resource-pattern="autowire/*.class" /> <!-- 表示指定掃描com.djh.demo.spring.beans.autowire下的所有類 -->
- 如下所示:
-
結構:
Structor -
配置文件:
Configuration -
各個類的注解:
Person.java:
Annotation
MockController.java:
Annotation
DataBaseMockImp.java:
Annotation
ServiceMock.java:
Annotation
測試結果:
result -
<context:include-filter>
子節(jié)點表示要包含的目標類,需要將<context:component-scan>
的use-default-filters
屬性的值設置為false. -
<context:exclude-filter>
子節(jié)點表示要排除在外的目標類 -
<context:component-scan>
下可以擁有若干個<context:include-filter>
和<context:exclude-filter>
子節(jié)點
-
- 使用注解裝配Bean與Bean之間的關聯關系(組件裝配):
<context:component-scan>
元素會自動注冊AutowiredAnnotationBeanPostProcessor實例,該實例可以自動裝配具有@Autowired
和@Resource
断部、@Inject
注解的屬性-
如:
Autowire
Autowire -
測試結果:
result -
@AutoWired
自動裝具有兼容類型的單個Bean屬性:- 構造器,普通字段(即使非public),一切具有參數的方法都可以應用
@Autowired
注解 - 默認情況下,所有使用@Autowired注解的屬性都需要被設置,當Spring找不帶匹配的Bean裝配屬性時,會拋出異常,若某一屬性允許不被設置,可以設置@Autowired注解的required屬性為false.
- 構造器,普通字段(即使非public),一切具有參數的方法都可以應用
-
-
@Resource
注解要求一個Bean名稱的屬性,若該屬性為空,則自動采用標注處的變量或方法名作為Bean的名稱
Spring AOP:
-
AOP
(Aspect-Oriented-Programming)- 解決日志以及代碼的混亂問題
- AOP:面向切面編程,是一種新的方法論,是對傳統(tǒng)的OOP的補充
- AOP的主要編程對象是切面,而切面模塊化切關注點
- AOP的優(yōu)點:
- 每個事物邏輯位于一個位置,代碼不分散,便于維護和升級
- 業(yè)務模塊更簡潔,只包含核心業(yè)務代碼
- 動態(tài)代理的方式處理日志:
-
被代理對象:
Object -
被代理對象實現類:
Object implement class -
代理類:
Proxy class -
測試類:
Test class
-
-
AOP分析:
- AOP關鍵詞:
- 切面(
Aspect
):橫切關注點被模塊化的特殊對象 - 通知(
Advice
):切面必須要完成的工作 - 目標(
Target
):被通知的對象 - 代理(
Proxy
):向目標對象應用通知之后創(chuàng)建的對象 - 連接點(
Joinpoint
):程序執(zhí)行的某個特定位置,如某個方法調用前猎贴、調用后、拋出異常等 - 切點(
pointcut
):每個類都擁有多個連接點蝴光。AOP通過切點定位到特定的連接點,一個切點可對應多個連接點
- 切面(
-
AspectJ(Spring2.0以上)為Java社區(qū)中最完整最流行的AOP框架,配置方式有以下兩種:
- 基于注解
- 基于XML
- 基于注解AspectJ注解支持:
- 必須在classpath下包含AspectJ類庫:
aopalliance.jar她渴、aspectj.weaver.jar、spring-aspects.jar
- 將aop Schema添加到
<beans>
根元素中 - 要在Spring IOC容器中啟用AspectJ注解支持,只要在Bean配置文件中定義一個空的XML元素
<aop:aspectj-autoproxy>
- 必須要在Bean配置文件中配置需要的Bean,通過
<context:component-scan/>
元素
- 必須在classpath下包含AspectJ類庫:
- 當Spring IOC容器偵測到Bean配置文件中的
<aop:aspectj-autoproxy>
元素時,會自動為與AspectJ切面匹配的Bean創(chuàng)建代理 - 使用注解聲明一個切面需要兩步:
- 把相應的類加到IOC容器中
- 聲明該類為一個切面
- 聲明執(zhí)行的位置
- 在配置文件中加入:
<!-- 使AspectJ注解起作用, 自動為匹配的類生成代理對象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 如:
-
結構:
structure -
注解:
annotation -
配置:
configuration -
測試結果:
Test result
-
- 在AspectJ注解中,切面只是一個帶有
@Aspect
注解的Java類 - 通知就是標注有某種注解的簡單的Java方法
- AspectJ支持5種類型的通知注解:
-
@Before
:前置通知,在方法執(zhí)行之前執(zhí)行
annotation -
@After
:后置通知,在方法執(zhí)行之后執(zhí)行,無論是否發(fā)生異常都會執(zhí)行
annotation -
@AfterRunning
:返回通知,在方法返回結果之后執(zhí)行
annotation -
@AfterThrowing
:異常通知,在方法拋出異常之后會執(zhí)行
annotation -
@Around
:環(huán)繞通知,圍繞著方法執(zhí)行
-
- 切面優(yōu)先級的指定:
- 通過加入注解
@Order(number)
, number值越小,優(yōu)先級越高
- 通過加入注解
- 重用切入點表達式:
-
通過定義一個聲明的方法
-
對于非當前類的其他類中的方法,可以使用如下形式:(包名+類名+方法名)
-
- 基于XML配置文件的方式來配置AOP:
-
結構:
Structure -
切面類:
Aspect -
配置文件:
Config -
測試結果:
TR
-
Spring對JDBC的支持:
- 使用JdbcTemplate更新數據庫
- 用sql語句和參數更新數據庫(update)
public int update(String sql, Object ... args) throw DataAccessException
- 批量更新數據庫(batchUpdate)
public int[] batchUpdate(String sql, List<Object[]> batchArgs)
- 查詢多行(query)
public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object... args)throws DataAccessException
- 單值查詢(queryForObject)
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throw DataAccessException
- 用sql語句和參數更新數據庫(update)
- 配置文件獲取數據庫連接信息:
-
結構:
- springContext.xml
<!-- 導入資源文件 --> <context:property-placeholder location ="classpath:db.properties" /> <!-- 配置C3p0數據源 --> <bean id ="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource"> <property name = "user" value = "${user}"></property> <property name = "password" value = "${password}"></property> <property name = "driverClass" value = "${driverClass}"></property> <property name = "jdbcUrl" value = "${jdbcUrl}"></property> <property name = "maxPoolSize" value = "${maxPoolSize}" ></property> <property name = "initialPoolSize" value = "${initialPoolSize}"></property> </bean>
- db.properties:
user = root password = java driverClass = com.mysql.jdbc.Driver jdbcUrl = jdbc:mysql://localhost:3306/spring maxPoolSize = 10 initialPoolSize = 5
- JdbcTemplate的配置蔑祟,配置信息如下:
<!-- 配置Spring的JdbcTemplate --> <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate"> <property name = "dataSource" ref = "dataSource" ></property> </bean>
-
測試結果:
-
- JdbcTemplate的單批更新插入與批量插入:
-
方法:
Implement -
測試結果:
TR
-
- JdbcTemplate的查詢:(
queryForObject趁耗、queryForList
用于獲取某一列的值)-
方法:
Implement -
測試結果:
TR
-
- JdbcTemplate不支持級聯屬性
- JdbcTemplate是線程安全的,故可以在IOC容器中聲明它的單個實例,并將這個實例注入到所有的DAO實例中,如:
-
DAO類:
DAO -
配置DAO依賴注入JdbcTemplate:
-
測試結果:
TR
- spring JDBC框架還提供了一個
JdbcDaoSupport
類來簡化DAO實現,該類聲明了jdbcTemplate屬性,它可以從IOC容器中注入.或者從數據源中創(chuàng)建 - Spring使用
NamedParameterJdbcTemplate
- 經典JDBC中,SQL參數使用占位符(?)表示
- 在Spring JDBC框架中,綁定SQL參數的另一種方式是使用具名參數(named parameter),也即是綁定變量(bind variable)
- 具名參數只在NamedParameterJdbcTemplate中得到支持
- 配置形式:
<!-- 配置具名參數 --> <bean id = "namedParameterJdbcTemplate" class ="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref = "jdbcTemplate"></constructor-arg> <--NamedParameterJdbcTemplate沒有無參構造器,必須提供參數--> </bean>
-
如:
-
使用具名參數可以傳遞對象進行操作,如:
Spring事物管理
- 用于確保數據的完整性與一致性
- 事物的四個關鍵屬性(ACID)
- 原子性(
automicity
) - 一致性(
consistency
) - 隔離性(
isolation
) - 持久性(
durability
)
- 原子性(
- Spring中的事物管理:
- Spring既支持編程式事物管理,也支持聲明式事物管理
- 編程式事物管理:將事物管理代碼嵌入到業(yè)務方法中來控制事物的提交和回滾
- 聲明式事物管理:將事物管理代碼從業(yè)務方法中分離出來,以聲明的方式來實現事物管理,可以通過AOP方法模塊化,Spring通過Spring AOP框架支持聲明式事物管理
- Spring既支持編程式事物管理,也支持聲明式事物管理
- Spring的核心事物管理抽象是Interface PlatformTransactionManager,管理封裝了一組獨立于技術的方法
- Spring中的事物管理器的不同實現:
-
Class DataSourceTransactionManager
:在應用程序中只需要處理一個數據源,且通過JDBC存取 -
Class JtaTransactionManager
:在JavaEE應用服務器上用JTA(Java Transaction API)進行管理 -
Class HibernateTransactionManager
:用Hibernate框架存取數據庫
... - 事物管理器以普通的Bean形式聲明在Spring IOC容器中
- 聲明式事物:
- 配置事物管理器:
<!-- 配置事物管理器 --> <bean id= "dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 使用注解事物時,需要啟用事物注解 --> <tx:annotation-driven transaction-manager = "dataSourceTransactionManager"/>
- 事物注解,使用
@Transactional
,如:
- Spring事物的傳播行為:
- 當事物方法被另一個事物方法調用時,必須指定事物應該如何傳播
- 事物的傳播行為可以由傳播屬性指定
- Spring支持的事物傳播行為有以下幾種:
-
REQUIRED
(默認的傳播行為,即使用調用方法的事物) REQUIRED_NEW
SUPPORTS
NOT_SUPPORTED
MANDATORY
NEVER
NESTED
-
- 使用propagation指定傳播行為,如:
@Transactional (propagation=Propagation.REQUIRED)
- Spring通過注解設置事物隔離級別疆虚、回滾苛败、只讀满葛、過期:
- 使用isolation指定事物的隔離級別
- 回滾:默認情況下,Spring的聲明式事物對所有的運行時異常進行回滾,可以通過以下屬性設置,一般不做設置:
noRollbackFor
rollbackFor
rollbackForClassName
- 只讀:該屬性通過readOnly設置,取值為true或false,表示這個事物只讀取數據但不更新數據,這樣可以幫助數據庫引擎優(yōu)化事物
- 過期(超時):使用timeout指定強制回滾之前事物可以占用的時間,單位為秒(S),如ATM機的取款倒計時
-
如:
-
- 回滾:默認情況下,Spring的聲明式事物對所有的運行時異常進行回滾,可以通過以下屬性設置,一般不做設置:
- Spring通過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"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:tx = "http://www.springframework.org/schema/tx"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 注解方式自動配置Bean -->
<!--
<context:component-scan base-package="com.djh.spring.transaction"></context:component-scan>
-->
<!-- 導入資源文件 -->
<context:property-placeholder location = "classpath:db.properties"/>
<!-- 配置C3p0數據源 -->
<bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
<property name = "user" value = "${user}" ></property>
<property name = "password" value = "${password}"></property>
<property name = "driverClass" value = "${driverClass}"></property>
<property name = "jdbcUrl" value = "${jdbcUrl}" ></property>
<property name = "maxPoolSize" value = "${maxPoolSize}"></property>
<property name = "initialPoolSize" value = "${initialPoolSize}"></property>
</bean>
<!-- 配置Spring的JdbcTemplate -->
<bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" ></property>
</bean>
<!-- 配置具名參數 -->
<bean id = "namedParameterJdbcTemplate" class = "org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref = "jdbcTemplate" ></constructor-arg>
</bean>
<!-- 配置事物管理器 -->
<bean id = "dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name = "dataSource" ref = "dataSource"></property>
</bean>
<!-- 配置Bean -->
<bean id = "bookShopDAO" class = "com.djh.spring.transaction.BookShopDaoImp">
<property name = "jdbcTemplate" ref = "jdbcTemplate"></property>
</bean>
<bean id = "bookShopService" class = "com.djh.spring.transaction.BookShopServiceImp">
<property name = "bookShopDao" ref = "bookShopDAO" ></property>
</bean>
<!-- 配置事物屬性 -->
<tx:advice id = "txAdvice" transaction-manager = "dataSourceTransactionManager">
<tx:attributes>
<!-- 根據方法名配置 -->
<tx:method name = "service" propagation = "REQUIRES_NEW" />
<tx:method name = "*" />
</tx:attributes>
</tx:advice>
<!-- 配置事物切入點,將事物切入點與事物屬性關聯 -->
<aop:config>
<aop:pointcut expression = "execution(* com.djh.spring.transaction.BookShopDao.*(..))" id = "txPointCut" />
<aop:advisor advice-ref = "txAdvice" pointcut-ref = "txPointCut"/>
</aop:config>
<!-- 注解的方式,啟用事物注解 -->
<!--
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
-->
</beans>