Spring框架的學習路線:java
- Spring第一天:Spring的IOC容器之XML的方式,Spring框架與Web項目整合
- Spring次日:Spring的IOC容器之註解的方式,Spring的AOP技術
- Spring第三天:Spring的事務管理、Spring框架的JDBC模板
- Spring第四天:SSH三大框架的整合
這是第三天學習大綱:mysql
大概步驟以下:spring
1. 步驟一:建立JavaWEB項目,引入具體的開發的jar包
* 先引入Spring框架開發的基本開發包
* 再引入Spring框架的AOP的開發包
* spring的傳統AOP的開發的包
* spring-aop-4.2.4.RELEASE.jar
* com.springsource.org.aopalliance-1.0.0.jar
* aspectJ的開發包
* com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
* spring-aspects-4.2.4.RELEASE.jar
2. 步驟二:建立Spring的配置文件,引入具體的AOP的schema約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
3. 步驟三:建立包結構,編寫具體的接口和實現類
* com.itheima.demo1
* CustomerDao -- 接口
* CustomerDaoImpl -- 實現類
4. 步驟四:將目標類配置到Spring中
<bean id="customerDao" class="com.itheima.demo1.CustomerDaoImpl"/>
5. 步驟五:定義切面類
* 添加切面和通知的註解
* @Aspect -- 定義切面類的註解
* 通知類型(註解的參數是切入點的表達式)
* @Before -- 前置通知
* @AfterReturing -- 後置通知
* @Around -- 環繞通知
* @After -- 最終通知
* @AfterThrowing -- 異常拋出通知
* 具體的代碼以下
@Aspect
public class MyAspectAnno {
@Before(value="execution(public void com.itheima.demo1.CustomerDaoImpl.save())")
public void log(){
System.out.println("記錄日誌...");
}
}
6. 步驟六:在配置文件中定義切面類
<bean id="myAspectAnno" class="com.itheima.demo1.MyAspectAnno"/>
7. 步驟七:在配置文件中開啓自動代理
<aop:aspectj-autoproxy/>
8. 完成測試
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="customerDao")
private CustomerDao customerDao;
@Test
public void run1(){
customerDao.save();
customerDao.update();
}
}
複製代碼
-----------------------------------------------直接上代碼學習-------------------------------------------------sql
MyAspectAnno.java:數據庫
/** * 註解方式的切面類 * @author Administrator */
@Aspect
public class MyAspectAnno {
/** 方式1: @Before(value="execution(public * com.itheima.demo1.CustomerDaoImpl.save())") public void log(){ System.out.println("記錄日誌..."); } */
/** 方式2:(使用自定義切入點) * 通知類型:@Before前置通知(切入點的表達式) */
@Before(value="MyAspectAnno.fn()")
public void log(){
System.out.println("記錄日誌...");
}
/** * 最終通知:方法執行成功或者右異常,都會執行 */
@After(value="MyAspectAnno.fn()")
public void after(){
System.out.println("最終通知...");
}
/** * 環繞通知 */
@Around(value="MyAspectAnno.fn()")
public void around(ProceedingJoinPoint joinPoint){
System.out.println("環繞通知1...");
try {
// 讓目標對象的方法執行
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("環繞通知2...");
}
/** * 自動定義切入點 @Pointcut */
@Pointcut(value="execution(public * com.itheima.demo1.CustomerDaoImpl.save())")
public void fn(){}
}
複製代碼
applicationContext.xml 添加:apache
<!-- 開啓自動代理 -->
<aop:aspectj-autoproxy/>
<!-- 配置目標對象 -->
<bean id="customerDao" class="com.itheima.demo1.CustomerDaoImpl"/>
<!-- 配置切面類 -->
<bean id="myAspectAnno" class="com.itheima.demo1.MyAspectAnno"/>
複製代碼
測試 Demo1.java:編程
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="customerDao")
private CustomerDao customerDao;
@Test
public void run1(){
customerDao.save();
customerDao.update();
}
}
複製代碼
通知類型:安全
1. 通知類型
* @Before -- 前置通知
* @AfterReturing -- 後置通知
* @Around -- 環繞通知(目標對象方法默認不執行的,須要手動執行)
* @After -- 最終通知
* @AfterThrowing -- 異常拋出通知
2. 配置通用的切入點
* 使用@Pointcut定義通用的切入點
@Aspect
public class MyAspectAnno {
@Before(value="MyAspectAnno.fn()")
public void log(){
System.out.println("記錄日誌...");
}
@Pointcut(value="execution(public void com.itheima.demo1.CustomerDaoImpl.save())")
public void fn(){}
}
複製代碼
1. 步驟一:建立數據庫的表結構
create database spring_day03;
use spring_day03;
create table t_account(
id int primary key auto_increment,
name varchar(20),
money double
);
2. 引入開發的jar包
* 先引入IOC基本的6個jar包
* 再引入Spring-aop的jar包
* 最後引入JDBC模板須要的jar包
* MySQL數據庫的驅動包:mysql-connector-java-5.1.7-bin.jar
* Spring-jdbc.jar
* Spring-tx.jar
3. 編寫測試代碼(本身來new對象的方式)
@Test
public void run1(){
// 建立鏈接池,先使用Spring框架內置的鏈接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_day03");
dataSource.setUsername("root");
dataSource.setPassword("root");
// 建立模板類
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// 完成數據的添加
jdbcTemplate.update("insert into t_account values (null,?,?)", "測試",10000);
}
複製代碼
如上使用的爲 Spring 框架內置的鏈接池。bash
上節中直接在測試代碼中編寫(即本身 new 對象的方式),咱們難道不能夠把鏈接池、模板類交給 Spring 管理嗎?能夠的。以下:app
在 applicationContext.xml 添加:
<!-- 內置的鏈接池:先配置鏈接池 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day03"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置JDBC的模板類 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼
而後測試就能夠這樣編寫了:
/** * 測試JDBC的模板類,使用IOC的方式 * @author Administrator */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1_1 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void run1(){
jdbcTemplate.update("insert into t_account values (null,?,?)", "小蒼",10000);
}
}
複製代碼
總結步驟以下:
1. 剛纔編寫的代碼使用的是new的方式,應該把這些類交給Spring框架來管理。
2. 修改的步驟以下
* 步驟一:Spring管理內置的鏈接池
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day03"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
* 步驟二:Spring管理模板類
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
* 步驟三:編寫測試程序
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void run2(){
jdbcTemplate.update("insert into t_account values (null,?,?)", "測試2",10000);
}
}
複製代碼
若是使用的不是 Spring 內置的鏈接池,使用的開源的鏈接池,該如何管理開源的鏈接池呢:
1. 管理DBCP鏈接池
* 先引入DBCP的2個jar包
* com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
* com.springsource.org.apache.commons.pool-1.5.3.jar
* 編寫配置文件
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day03"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
2. 管理C3P0鏈接池
* 先引入C3P0的jar包
* com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
* 編寫配置文件
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
複製代碼
1. 增刪改查的操做
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
// 插入操做
public void demo1(){
jdbcTemplate.update("insert into account values (null,?,?)", "冠希",10000d);
}
@Test
// 修改操做
public void demo2(){
jdbcTemplate.update("update account set name=?,money =? where id = ?", "思雨",10000d,5);
}
@Test
// 刪除操做
public void demo3(){
jdbcTemplate.update("delete from account where id = ?", 5);
}
@Test
// 查詢一條記錄
public void demo4(){
Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new BeanMapper(), 1);
System.out.println(account);
}
@Test
// 查詢全部記錄
public void demo5(){
List<Account> list = jdbcTemplate.query("select * from t_account", new BeanMapper());
for (Account account : list) {
System.out.println(account);
}
}
}
class BeanMapper implements RowMapper<Account>{
public Account mapRow(ResultSet rs, int arg1) throws SQLException {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
複製代碼
查詢全部記錄 demo5( )方法的輸出結果以下:
1. 事務:指的是邏輯上一組操做,組成這個事務的各個執行單元,要麼一塊兒成功,要麼一塊兒失敗!
2. 事務的特性
* 原子性
* 一致性
* 隔離性
* 持久性
3. 若是不考慮隔離性,引起安全性問題
* 讀問題:
* 髒讀:
* 不可重複讀:
* 虛讀:
* 寫問題:
* 丟失更新:
4. 如何解決安全性問題
* 讀問題解決,設置數據庫隔離級別
* 寫問題解決可使用 悲觀鎖和樂觀鎖的方式解決
複製代碼
1. PlatformTransactionManager接口 -- 平臺事務管理器.(真正管理事務的類)。該接口有具體的實現類,根據不一樣的持久層框架,須要選擇不一樣的實現類!
2. TransactionDefinition接口 -- 事務定義信息.(事務的隔離級別,傳播行爲,超時,只讀)
3. TransactionStatus接口 -- 事務的狀態
4. 總結:上述對象之間的關係:平臺事務管理器真正管理事務對象.根據事務定義的信息TransactionDefinition 進行事務管理,在管理事務中產生一些狀態.將狀態記錄到TransactionStatus中
5. PlatformTransactionManager接口中實現類和經常使用的方法
1. 接口的實現類
* 若是使用的Spring的JDBC模板或者MyBatis框架,須要選擇DataSourceTransactionManager實現類
* 若是使用的是Hibernate的框架,須要選擇HibernateTransactionManager實現類
2. 該接口的經常使用方法
* void commit(TransactionStatus status)
* TransactionStatus getTransaction(TransactionDefinition definition)
* void rollback(TransactionStatus status)
6. TransactionDefinition
1. 事務隔離級別的常量
* static int ISOLATION_DEFAULT -- 採用數據庫的默認隔離級別
* static int ISOLATION_READ_UNCOMMITTED
* static int ISOLATION_READ_COMMITTED
* static int ISOLATION_REPEATABLE_READ
* static int ISOLATION_SERIALIZABLE
2. 事務的傳播行爲常量(不用設置,使用默認值)
* 先解釋什麼是事務的傳播行爲:解決的是業務層之間的方法調用!!
* PROPAGATION_REQUIRED(默認值) -- A中有事務,使用A中的事務.若是沒有,B就會開啓一個新的事務,將A包含進來.(保證A,B在同一個事務中),默認值!!
* PROPAGATION_SUPPORTS -- A中有事務,使用A中的事務.若是A中沒有事務.那麼B也不使用事務.
* PROPAGATION_MANDATORY -- A中有事務,使用A中的事務.若是A沒有事務.拋出異常.
* PROPAGATION_REQUIRES_NEW(記)-- A中有事務,將A中的事務掛起.B建立一個新的事務.(保證A,B沒有在一個事務中)
* PROPAGATION_NOT_SUPPORTED -- A中有事務,將A中的事務掛起.
* PROPAGATION_NEVER -- A中有事務,拋出異常.
* PROPAGATION_NESTED(記) -- 嵌套事務.當A執行以後,就會在這個位置設置一個保存點.若是B沒有問題.執行經過.若是B出現異常,運行客戶根據需求回滾(選擇回滾到保存點或者是最初始狀態)
複製代碼
關於事務的傳播行爲的理解能夠先看下圖:
這裏 save 方法當作 A,find 方法當作 B,假設傳播行爲設置爲 PROPAGATION_SUPPORTS
,則 A 中有事務,使用 A 中的事務,若是 A 中沒有事務,那麼 B 也不使用事務。
1. 步驟一:建立WEB工程,引入須要的jar包
* IOC的6個包
* AOP的4個包
* C3P0的1個包
* MySQL的驅動包
* JDBC目標2個包
* 整合JUnit測試包
2. 步驟二:引入配置文件
* 引入配置文件
* 引入log4j.properties
* 引入applicationContext.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
3. 步驟三:建立對應的包結構和類
* com.itheima.demo1
* AccountService
* AccountServlceImpl
* AccountDao
* AccountDaoImpl
4. 步驟四:引入Spring的配置文件,將類配置到Spring中
<bean id="accountService" class="com.itheima.demo1.AccountServiceImpl">
</bean>
<bean id="accountDao" class="com.itheima.demo1.AccountDaoImpl">
</bean>
5. 步驟五:在業務層注入DAO ,在DAO中注入JDBC模板(強調:簡化開發,之後DAO能夠繼承JdbcDaoSupport類)
<bean id="accountService" class="com.itheima.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.itheima.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
6. 步驟六:編寫DAO和Service中的方法
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
public void outMoney(String out, double money) {
this.getJdbcTemplate().update("update t_account set money = money = ? where name = ?", money,out);
}
public void inMoney(String in, double money) {
this.getJdbcTemplate().update("update t_account set money = money + ? where name = ?", money,in);
}
}
7. 步驟七:編寫測試程序.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void run1(){
accountService.pay("冠希", "美美", 1000);
}
}
複製代碼
關於步驟 5 中,AccountDaoImpl.java 代碼按理應該以下這樣寫:
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//扣錢
public void outMoney(String out, double money) {
jdbcTemplate.update("update t_account set money = money - ? where name = ?", money,out);
}
//加錢
public void inMoney(String in, double money) {
jdbcTemplate.update("update t_account set money = money + ? where name = ?", money,in);
}
}
複製代碼
按邏輯來講來講在業務層注入 DAO ,在 DAO 中注入 JDBC 模板,applicationContext.xml 添加以下:
<!-- 配置C3P0的鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置JDBC的模板類。 在 JDBC 模板注入鏈接池-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- DAO 中注入 JDBC 模板 -->
<bean id="accountDao" class="com.itheima.demo1.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
複製代碼
解釋: 畢竟業務層須要操做 Dao 層對象,Dao 層須要操做 JDBC 模板類對象,JDBC 須要鏈接池對象,因此如上。
可是爲了簡化開發,其實 DAO 能夠繼承 JdbcDaoSupport 這個類?AccountDaoImpl.java 能夠以下編寫:(繼承 JdbcDaoSupport )
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
//扣錢
public void outMoney(String out, double money) {
this.getJdbcTemplate().update("update t_account set money = money - ? where name = ?", money,out);
}
//加錢
public void inMoney(String in, double money) {
this.getJdbcTemplate().update("update t_account set money = money + ? where name = ?", money,in);
}
}
複製代碼
JdbcDaoSupport 是一個什麼類?能夠查看源代碼發現:
能夠看到 setDataSource( ) 方法中若是模板類對象爲空,會根據鏈接池建立一個模板,並賦值給成員屬性模板類對象 jdbcTemplate。這裏代碼啥意思?劃重點,這裏代碼表示建立模板對象以前的前提得是,我先有一個鏈接池,再根據鏈接池建立 JDBC 模板類對象。
因此在配置文件寫注入配置的時候,DAO 層能夠考慮這樣寫:
<bean id="accountDao" class="com.itheima.demo1.AccountDaoImpl">
<!-- <property name="jdbcTemplate" ref="jdbcTemplate"/> -->
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼
直接注入鏈接池便可,而不須要再注入 JDBC 模板類。由於注入鏈接池以後,底層會根據鏈接池建立一個 JDBC 模板。(請再回頭看 JdbcDaoSupport 源碼截圖體會。)
推導過程:
1. Spring的事務管理的分類
1. Spring的編程式事務管理(不推薦使用)
* 經過手動編寫代碼的方式完成事務的管理(不推薦)
2. Spring的聲明式事務管理(底層採用AOP的技術)
* 經過一段配置的方式完成事務的管理(重點掌握註解的方式)
複製代碼
一、Spring框架的事務管理之編程式的事務管理(瞭解)
1. 說明:Spring爲了簡化事務管理的代碼:提供了模板類 TransactionTemplate,因此手動編程的方式來管理事務,只須要使用該模板類便可!!
2. 手動編程方式的具體步驟以下:
1. 步驟一:配置一個事務管理器,Spring使用PlatformTransactionManager接口來管理事務,因此我們須要使用到他的實現類!!
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2. 步驟二:配置事務管理的模板
<!-- 配置事務管理的模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
3. 步驟三:在須要進行事務管理的類中,注入事務管理的模板.
<bean id="accountService" class="com.itheima.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
4. 步驟四:在業務層使用模板管理事務:
// 注入事務模板對象
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void pay(final String out, final String in, final double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 扣錢
accountDao.outMoney(out, money);
int a = 10/0;
// 加錢
accountDao.inMoney(in, money);
}
});
}
複製代碼
推導過程思路:
完整 applicationContext.xml 配置:
<!-- 配置C3P0的鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置平臺事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 手動編碼,提供了模板類,使用該類管理事務比較簡單 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!-- 配置JDBC的模板類 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> -->
<!-- 配置業務層和持久層 -->
<bean id="accountService" class="com.itheima.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
<bean id="accountDao" class="com.itheima.demo1.AccountDaoImpl">
<!-- <property name="jdbcTemplate" ref="jdbcTemplate"/> -->
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼
二、Spring框架的事務管理之聲明式事務管理,即經過配置文件來完成事務管理(AOP思想)
聲明式事務管理又分紅兩種方式:
① 基於AspectJ的XML方式:(重點掌握)
1. 步驟一:恢復轉帳開發環境
2. 步驟二:引入AOP的開發包
3. 步驟三:配置事務管理器
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
4. 步驟四:配置事務加強
<!-- 配置事務加強 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
name :綁定事務的方法名,可使用通配符,能夠配置多個。
propagation :傳播行爲
isolation :隔離級別
read-only :是否只讀
timeout :超時信息
rollback-for:發生哪些異常回滾.
no-rollback-for:發生哪些異常不回滾.
-->
<!-- 哪些方法加事務 -->
<tx:method name="pay" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
5. 步驟五:配置AOP的切面
<!-- 配置AOP切面產生代理 -->
<aop:config>
<aop:advisor advice-ref="myAdvice" pointcut="execution(* com.itheima.demo2.AccountServiceImpl.pay(..))"/>
</aop:config>
* 注意:若是是本身編寫的切面,使用<aop:aspect>標籤,若是是系統製做的,使用<aop:advisor>標籤。
6. 步驟六:編寫測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Demo2 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void run1(){
accountService.pay("冠希", "美美", 1000);
}
}
複製代碼
applicationContext.xml:
<!-- 配置C3P0的鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置平臺事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 聲明式事務(採用XML配置文件的方式) -->
<!-- 先配置通知 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 給方法設置數據庫屬性(隔離級別,傳播行爲) -->
<tx:method name="pay" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置AOP:若是是本身編寫的AOP,使用aop:aspect配置,使用的是Spring框架提供的通知aop:advisor -->
<aop:config>
<!-- aop:advisor,是Spring框架提供的通知 -->
<aop:advisor advice-ref="myAdvice" pointcut="execution(public * com.itheima.demo2.AccountServiceImpl.pay(..))"/>
</aop:config>
<!-- 配置業務層和持久層 -->
<bean id="accountService" class="com.itheima.demo2.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.itheima.demo2.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼
② 基於AspectJ的註解方式:(重點掌握,最簡單的方式)
1. 步驟一:恢復轉帳的開發環境
2. 步驟二:配置事務管理器
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
3. 步驟三:開啓註解事務
<!-- 開啓註解事務 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
4. 步驟四:在業務層上添加一個註解:@Transactional
5. 編寫測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class Demo3 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void run1(){
accountService.pay("冠希", "美美", 1000);
}
}
複製代碼
注:關於步驟四,若是在類上添加了註解 @Transactional
,則表示類中全部方法所有都有事務。
applicationContext.xml:
<!-- 配置C3P0的鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置平臺事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 開啓事務的註解 -->
<tx:annotation-driven tr ansaction-manager="transactionManager"/>
<!-- 配置業務層和持久層 -->
<bean id="accountService" class="com.itheima.demo3.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.itheima.demo3.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼