淺嘗Spring註解開發_聲明式事務及原理 淺嘗Spring註解開發,基於Spring 4.3.12 包含聲明式事務使用、基本原理分析 淺嘗Spring註解開發_自定義註冊組件、屬性賦值、自動裝配 淺嘗Spring註解開發_Bean生命周期及執行過程 淺嘗Spring註解開發_AOP原理及完整過程分 ...
淺嘗Spring註解開發_聲明式事務及原理
淺嘗Spring註解開發,基於Spring 4.3.12
包含聲明式事務使用、基本原理分析
淺嘗Spring註解開發_自定義註冊組件、屬性賦值、自動裝配
淺嘗Spring註解開發_Bean生命周期及執行過程
淺嘗Spring註解開發_AOP原理及完整過程分析(源碼)
淺嘗Spring註解開發_聲明式事務及原理
淺嘗Spring註解開發_簡單理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
聲明式事務
環境搭建
-
添加依賴:數據源、資料庫驅動、Spring-jdbc模塊
-
業務類
UserDao
@Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; public void insert(){ String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)"; String username = UUID.randomUUID().toString().substring(0, 5); jdbcTemplate.update(sql, username,19); } }
UserService
@Service public class UserService { @Autowired private UserDao userDao; public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }
-
配置數據源、JdbcTemplate(Spring提供的簡化資料庫操作的工具)操作數據
@Configuration public class TxConfig { //數據源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring對@Configuration類會特殊處理;給容器中加組件的方法,多次調用都只是從容器中找組件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } }
開啟註解
-
給方法上標註 @Transactional 表示當前方法是一個事務方法
UserService
@Service public class UserService { @Autowired private UserDao userDao; @Transactional public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }
-
@EnableTransactionManagement 開啟基於註解的事務管理功能
@EnableTransactionManagement @Configuration public class TxConfig { //... }
-
配置事務管理器來控制事務
@EnableTransactionManagement @Configuration public class TxConfig { //數據源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring對@Configuration類會特殊處理;給容器中加組件的方法,多次調用都只是從容器中找組件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } //註冊事務管理器在容器中 @Bean public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }
-
測試
- 出現異常時會回滾,不會插入資料庫
public class IOCTest_Tx { @Test public void test01(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class); UserService userService = applicationContext.getBean(UserService.class); userService.insertUser(); applicationContext.close(); } }
原理分析
與AOP相似,註冊,包裝,增強器,攔截器,執行目標方法
淺嘗Spring註解開發_AOP原理及完整過程分析(源碼)
-
進入
@EnableTransactionManagement
-
利用
TransactionManagementConfigurationSelector
給容器中會導入組件,判斷AdviceMode
的值選擇導入哪個組件-
如果是
PROXY
導入兩個組件(預設)AutoProxyRegistrar(自動代理註冊器)
ProxyTransactionManagementConfiguration(代理事務管理配置)
-
如果是
ASPECTJ
導入TransactionManagementConfigUtils
-
-
-
分析
AutoProxyRegistrar
- 用於給容器中註入Bean,調用
registerBeanDefinitions()
- 調用
AopConfigUtils.registerAutoProxyCreatorIfNecessary()
最終註冊InfrastructureAdvisorAutoProxyCreator(基礎架構自動代理創建者)
組件,也是後置處理器類型,利用後置處理器機制在對象創建以後,包裝對象,返回一個代理對象(增強器),代理對象執行方法利用攔截器鏈進行調用 - 這個類中同時註冊了一個
AnnotationAwareAspectJAutoProxyCreator(註解裝配模式的AspectJ切麵自動代理創建器)
,這個就是在AOP一開始註冊的那個類,用於Bean實例化時的後置處理器
- 用於給容器中註入Bean,調用
-
分析
ProxyTransactionManagementConfiguration
-
給容器中註冊事務增強器,如
BeanFactoryTransactionAttributeSourceAdvisor(BeanFactory事務屬性源增強器)
-
事務增強器要用事務註解的信息,
AnnotationTransactionAttributeSource
解析事務註解 -
事務攔截器:
-
TransactionInterceptor
(它是一個MethodInterceptor
方法攔截器,和AOP中是相同的):保存了事務屬性信息,事務管理器 -
在目標方法執行的時候執行攔截器鏈
-
事務攔截器
-
先獲取事務相關的屬性
-
再獲取
PlatformTransactionManager
,如果事先沒有添加指定任何transactionmanger
最終會從容器中按照類型獲取一個
PlatformTransactionManager
-
執行目標方法
invokeWithinTransaction(){ invocation.proceedWithInvocation() }
- 如果異常,獲取到事務管理器,利用事務管理回滾操作
txInfo.getTransactionManager().rollback()
- 如果正常,利用事務管理器,提交事務
txInfo.getTransactionManager().commit()
- 如果異常,獲取到事務管理器,利用事務管理回滾操作
-
-
-
-