Spring中的事務攔截器順序如何控制詳解
1、前言
咱們知道 Spring 事務是通過aop的方式添加了一個事務攔截器,事務攔截器會攔截目標方法的執(zhí)行,在方法執(zhí)行前后添加了事務控制。
那么spring事務攔截器的順序如何控制呢,若我們自己也添加了一些攔截器,此時事務攔截器和自定義攔截器共存的時候,他們的順序是怎么執(zhí)行的?如何手動來控制他們的順序??
可能有些朋友會問,控制他們的順序,這個功能有什么用呢?為什么要學這個
學會了這些,你可以實現很多牛逼的功能,比如
1、讀寫分離
2、通用冪等框架
3、分布式事務框架
對這些有興趣么?那么咱們繼續(xù)。
2、事務攔截器順序設置
@EnableTransactionManagement 注解有個 order屬性,默認值是Integer.MAX_VALUE,用來指定事務攔截器的順序,值越小,攔截器的優(yōu)先級越高,如:
@EnableTransactionManagement(order = 2)
下面來看案例。
3、案例
我們自定義2個攔截器:一個放在事務攔截器之前執(zhí)行,一個放在事務攔截器之后執(zhí)行
攔截器 | 順序 |
TransactionInterceptorBefore | 1 |
@EnableTransactionManagement 事務攔截器 | 2 |
TransactionInterceptorAfter | 3 |
3.1、準備sql
DROP DATABASE IF EXISTS javacode2018; CREATE DATABASE if NOT EXISTS javacode2018; USE javacode2018; DROP TABLE IF EXISTS t_user; CREATE TABLE t_user( id int PRIMARY KEY AUTO_INCREMENT, name varchar(256) NOT NULL DEFAULT '' COMMENT '姓名' );
3.2、Spring配置類MainConfig10
@1:開啟了事務管理功能,并且設置了事務攔截器的順序是2,spring事務攔截器完整類名是
org.springframework.transaction.interceptor.TransactionInterceptor
@2:開啟aop功能
package com.javacode2018.tx.demo10; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration //說明當前類是一個配置類 @ComponentScan //開啟bean自動掃描注冊功能 @EnableTransactionManagement(order = 2) //@1:設置事務攔截器的順序是2 @EnableAspectJAutoProxy // @2:開啟@Aspect Aop功能 public class MainConfig10 { @Bean public DataSource dataSource() { org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8"); dataSource.setUsername("root"); dataSource.setPassword("root123"); dataSource.setInitialSize(5); return dataSource; } //定義一個jdbcTemplate @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } //定義事務管理器transactionManager @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
3.3、定義一個有事務的Service類
addUser方法上面添加了@Transactional注解,表示使用spring來管理事務,方法內部向db中插入了一條數據,為了方便分析結果,方法內部輸出了2行日志
package com.javacode2018.tx.demo10; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @Component public class UserService { @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void addUser() { System.out.println("--------UserService.addUser start"); this.jdbcTemplate.update("insert into t_user(name) VALUES (?)", "張三"); System.out.println("--------UserService.addUser end"); } }
3.4、自定義第1個攔截器,放在事務攔截器之前執(zhí)行
下面通過Aspect的方式定義了一個攔截器,順序通過**@Order(1)設置的是1**,那么這個攔截器會在事務攔截器之前執(zhí)行。
package com.javacode2018.tx.demo10; import org.aopalliance.intercept.Joinpoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Aspect @Order(1) //@1 public class TransactionInterceptorBefore { @Pointcut("execution(* com.javacode2018.tx.demo10.UserService.*(..))") public void pointcut() { } @Around("pointcut()") public Object tsBefore(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("--------before start!!!"); Object result = joinPoint.proceed(); System.out.println("--------before end!!!"); return result; } }
3.5、自定義第2個攔截器,放在事務攔截器后面執(zhí)行
這個攔截器的order是3,會在事務攔截器后面執(zhí)行。
package com.javacode2018.tx.demo10; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Aspect @Order(2) public class TransactionInterceptorAfter { @Pointcut("execution(* com.javacode2018.tx.demo10.UserService.*(..))") public void pointcut() { } @Around("pointcut()") public Object tsAfter(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("--------after start!!!"); Object result = joinPoint.proceed(); System.out.println("--------after end!!!"); return result; } }
3.6、添加測試類
package com.javacode2018.tx.demo10; import org.junit.Before; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; public class Demo10Test { private UserService userService; private JdbcTemplate jdbcTemplate; @Before public void before() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig10.class); userService = context.getBean(UserService.class); this.jdbcTemplate = context.getBean("jdbcTemplate", JdbcTemplate.class); jdbcTemplate.update("truncate table t_user"); } @Test public void test1() { this.userService.addUser(); } }
運行test1輸出:
--------before start!!!
--------after start!!!
--------UserService.addUser start
--------UserService.addUser end
--------after end!!!
--------before end!!!
結果和上圖中一致,大家可以在3個攔截器中設置一下斷點,調試一下可以看到更詳細的信息,可加深理解。
4、總結
今天的內容算是比較簡單的,重點要掌握如何設置事務攔截器的順序,@EnableTransactionManagement 有個 order屬性,默認值是Integer.MAX_VALUE,用來指定事務攔截器的順序,值越小,攔截器的優(yōu)先級越高。
后面我們會通過這個功能實現讀寫分離,通用冪等性的功能。
到此這篇關于Spring中的事務攔截器順序如何控制詳解的文章就介紹到這了,更多相關Spring事務攔截器順序內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot中間件ORM框架實現案例詳解(Mybatis)
這篇文章主要介紹了SpringBoot中間件ORM框架實現案例詳解(Mybatis),本篇文章提煉出mybatis最經典、最精簡、最核心的代碼設計,來實現一個mini-mybatis,從而熟悉并掌握ORM框架的涉及實現,需要的朋友可以參考下2023-07-07Java synchronized關鍵_動力節(jié)點Java學院整理
在java中,每一個對象有且僅有一個同步鎖。這也意味著,同步鎖是依賴于對象而存在。下面通過本文給大家介紹synchronized原理 及基本規(guī)則,感興趣的朋友一起學習吧2017-05-05Mybatis?Mapper中多參數方法不使用@param注解報錯的解決
這篇文章主要介紹了Mybatis?Mapper中多參數方法不使用@param注解報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01HTTP 415錯誤-Unsupported media type詳解
這篇文章主要介紹了HTTP 415錯誤-Unsupported media type詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08