Spring事務(wù)處理原理步驟詳解
1、事務(wù)處理實(shí)現(xiàn)
實(shí)現(xiàn)步驟:
* 聲明式事務(wù):
*
* 環(huán)境搭建:
* 1、導(dǎo)入相關(guān)依賴
* 數(shù)據(jù)源、數(shù)據(jù)庫驅(qū)動(dòng)、Spring-jdbc模塊
* 2、配置數(shù)據(jù)源、JdbcTemplate(Spring提供的簡化數(shù)據(jù)庫操作的工具)操作數(shù)據(jù)
* 3、給方法上標(biāo)注 @Transactional 表示當(dāng)前方法是一個(gè)事務(wù)方法;
* 4、 @EnableTransactionManagement 開啟基于注解的事務(wù)管理功能;
* @EnableXXX
* 5、配置事務(wù)管理器來控制事務(wù);
* @Bean
* public PlatformTransactionManager transactionManager()
代碼實(shí)現(xiàn):
@EnableTransactionManagement
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {
//數(shù)據(jù)源
@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;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception{
//Spring對@Configuration類會特殊處理;給容器中加組件的方法,多次調(diào)用都只是從容器中找組件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注冊事務(wù)管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception{
return new DataSourceTransactionManager(dataSource());
}
}
2、事務(wù)處理原理
原理分析:
* 原理:
* 1)、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector給容器中會導(dǎo)入組件
* 導(dǎo)入兩個(gè)組件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2)、AutoProxyRegistrar:
* 給容器中注冊一個(gè) InfrastructureAdvisorAutoProxyCreator 組件;
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置處理器機(jī)制在對象創(chuàng)建以后,包裝對象,返回一個(gè)代理對象(增強(qiáng)器),代理對象執(zhí)行方法利用攔截器鏈進(jìn)行調(diào)用;
*
* 3)、ProxyTransactionManagementConfiguration 做了什么?
* 1、給容器中注冊事務(wù)增強(qiáng)器;
* 1)、事務(wù)增強(qiáng)器要用事務(wù)注解的信息,AnnotationTransactionAttributeSource解析事務(wù)注解
* 2)、事務(wù)攔截器:
* TransactionInterceptor;保存了事務(wù)屬性信息,事務(wù)管理器;
* 他是一個(gè) MethodInterceptor;
* 在目標(biāo)方法執(zhí)行的時(shí)候;
* 執(zhí)行攔截器鏈;
* 事務(wù)攔截器:
* 1)、先獲取事務(wù)相關(guān)的屬性
* 2)、再獲取PlatformTransactionManager,如果事先沒有添加指定任何transactionmanger
* 最終會從容器中按照類型獲取一個(gè)PlatformTransactionManager;
* 3)、執(zhí)行目標(biāo)方法
* 如果異常,獲取到事務(wù)管理器,利用事務(wù)管理回滾操作;
* 如果正常,利用事務(wù)管理器,提交事務(wù)
*
*/
核心代碼
1、EnableTransactionManagement注解,注入TransactionManagementConfigurationSelector類
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
2、TransactionManagementConfigurationSelector類,最終會導(dǎo)入AutoProxyRegistrar.class和ProxyTransactionManagementConfiguration.class兩個(gè)組件。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
3、AutoProxyRegistrar類的作用為:
給容器中注冊一個(gè) InfrastructureAdvisorAutoProxyCreator 組件;
最終的目的是:利用后置處理器機(jī)制在對象創(chuàng)建以后,包裝對象,返回一個(gè)代理對象(增強(qiáng)器),代理對象執(zhí)行方法利用攔截器鏈進(jìn)行調(diào)用;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}

InfrastructureAdvisorAutoProxyCreator類的作用與AnnotationAwareAspectJAutoProxyCreator類的作用類似。
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
4、ProxyTransactionManagementConfiguration類
代理事務(wù)管理配置類
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
TransactionInterceptor類,事務(wù)調(diào)用:invokeWithinTransaction()方法為最終執(zhí)行的方法
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
TransactionAspectSupport類的最終事務(wù)方法執(zhí)行:
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Spring事務(wù)失效問題分析及解決方案
- 這一次搞懂Spring事務(wù)是如何傳播的
- 使用SpringBoot注解方式處理事務(wù)回滾實(shí)現(xiàn)
- springboot手動(dòng)事務(wù)回滾的實(shí)現(xiàn)代碼
- MySQL事務(wù)及Spring隔離級別實(shí)現(xiàn)原理詳解
- Spring注解 TX聲明式事務(wù)實(shí)現(xiàn)過程解析
- Springboot通過aop實(shí)現(xiàn)事務(wù)控制過程解析
- Spring如何基于aop實(shí)現(xiàn)事務(wù)控制
- Spring中的事務(wù)管理實(shí)例詳解
- SpringMVC+MyBatis聲明式事務(wù)管理
- Spring事務(wù)管理只對出現(xiàn)運(yùn)行期異常進(jìn)行回滾
- SpringBoot 注解事務(wù)聲明式事務(wù)的方式
- Spring事務(wù)失效的幾種原因
相關(guān)文章
Java實(shí)現(xiàn)經(jīng)典游戲推箱子的示例代碼
《推箱子》推箱子是一個(gè)古老的游戲,目的是在訓(xùn)練你的邏輯思考能力。本文將利用Java實(shí)現(xiàn)這一經(jīng)典的小游戲,并采用了swing技術(shù)進(jìn)行了界面化處理,需要的可以參考一下2022-02-02
使用SpringBoot跨系統(tǒng)調(diào)用接口的方案
這篇文章主要介紹了使用SpringBoot跨系統(tǒng)調(diào)用接口的方案,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
Spring中@Scheduled和HttpClient的連環(huán)坑
這篇文章主要給大家介紹了關(guān)于Spring中@Scheduled和HttpClient的連環(huán)坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
@SpringBootTest 注解報(bào)紅問題及解決
這篇文章主要介紹了@SpringBootTest 注解報(bào)紅問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java中@Pattern注解常用的校驗(yàn)正則表達(dá)式學(xué)習(xí)筆記
對于正則這個(gè)東西,對我來說一直是很懵逼的,每次用每次查,然后還是記不住,下面這篇文章主要給大家介紹了關(guān)于Java中@Pattern注解常用的校驗(yàn)正則表達(dá)式學(xué)習(xí)筆記的相關(guān)資料,需要的朋友可以參考下2022-07-07
一文簡介Java中BlockingQueue阻塞隊(duì)列
本文主要介紹了一文簡介Java中BlockingQueue阻塞隊(duì)列,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

