可以用TransactionSynchronizationAdapter 这个类,
public abstract class TransactionSynchronizationAdapter implements TransactionSynchronization, Ordered { public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } public void suspend() { } public void resume() { } public void flush() { } public void beforeCommit(boolean readOnly) { } public void beforeCompletion() { } public void afterCommit() { } public void afterCompletion(int status) { } }
TransactionSynchronizationAdapter 会根据事务的完成状态去调用相应的afterCommit等
定义拦截方法注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AfterCommit { }
定义切面
@Aspect public class AfterCommitAnnotationAspect { private static final Logger LOGGER = Logger .getLogger(AfterCommitAnnotationAspect.class); private final AfterCommitExecutor afterCommitExecutor; @Autowired public AfterCommitAnnotationAspect(AfterCommitExecutor afterCommitExecutor) { this.afterCommitExecutor = afterCommitExecutor; } @Around(value = "@annotation(com.best.oasis.spring.transaction.AfterCommit)", argNames = "pjp") public Object aroundAdvice(final ProceedingJoinPoint pjp) { afterCommitExecutor.execute(new PjpAfterCommitRunnable(pjp)); return null; } private static final class PjpAfterCommitRunnable implements Runnable { private final ProceedingJoinPoint pjp; public PjpAfterCommitRunnable(ProceedingJoinPoint pjp) { this.pjp = pjp; } @Override public void run() { try { pjp.proceed(); } catch (Throwable e) { LOGGER.error("Exception while invoking pjp.proceed()", e); throw new RuntimeException(e); } } @Override public String toString() { String typeName = pjp.getTarget().getClass().getSimpleName(); String methodName = pjp.getSignature().getName(); return "PjpAfterCommitRunnable[type=" + typeName + ", method=" + methodName + "]"; } } }
执行器
public interface AfterCommitExecutor extends Executor { }
执行器实现,真正调用的地方
@Service public class AfterCommitExecutorImpl extends TransactionSynchronizationAdapter implements AfterCommitExecutor { private static final Logger LOGGER = Logger.getLogger(AfterCommitExecutorImpl.class); private static final ThreadLocal<List<Runnable>> RUNNABLES = new ThreadLocal<List<Runnable>>(); @Override public void execute(Runnable runnable) { LOGGER.info("Submitting new runnable {"+runnable+"} to run after commit"); if (!TransactionSynchronizationManager.isSynchronizationActive()) { LOGGER.info("Transaction synchronization is NOT ACTIVE. Executing right now runnable {"+runnable+"}"); runnable.run(); return; } List<Runnable> threadRunnables = RUNNABLES.get(); if (threadRunnables == null) { threadRunnables = new ArrayList<Runnable>(); RUNNABLES.set(threadRunnables); TransactionSynchronizationManager.registerSynchronization(this); } threadRunnables.add(runnable); } @Override public void afterCommit() { List<Runnable> threadRunnables = RUNNABLES.get(); LOGGER.info("Transaction successfully committed, executing {"+threadRunnables.size()+"} runnables" ); for (int i = 0; i < threadRunnables.size(); i++) { Runnable runnable = threadRunnables.get(i); LOGGER.info("Executing runnable {"+runnable+"}"); try { runnable.run(); } catch (RuntimeException e) { LOGGER.error("Failed to execute runnable " + runnable, e); } } } @Override public void afterCompletion(int status) { LOGGER.info("Transaction completed with status {"+(status == STATUS_COMMITTED ? "COMMITTED" : "ROLLED_BACK")+"}"); RUNNABLES.remove(); } }
相关推荐
当一个方法(A方法)内部调用另一个方法(B方法)时,可能会遇到事务控制的复杂情况。本示例代码旨在解决在A方法内部调用B方法时的回滚问题。 在Spring中,事务管理可以通过编程式和声明式两种方式实现。编程式事务...
- **配置事务管理器**:接下来,需要配置一个事务管理器(如`DataSourceTransactionManager`),它负责管理事务的开始、提交和回滚。 - **配置事务规则**:最后,需要配置事务规则,指定哪些方法需要在事务中执行。 ...
- **Spring AOP**:Spring AOP允许开发者将一些通用的业务逻辑(例如日志、事务管理等)从业务代码中抽离出来,形成一个独立的部分,即切面(Aspect)。这样做的好处是可以减少业务代码的耦合度,提高代码的可读性...
在压缩包中的Spring事务管理练习,你可以尝试创建一个简单的示例,例如模拟两个银行账户转账的过程,通过开启事务确保转账的原子性,即转账操作要么全部成功,要么全部失败。这样可以帮助你更好地理解Spring事务管理...
然而,在实际开发过程中,可能会遇到使用Spring MyBatis纯注解方式配置的事务无法正常提交的情况,尤其是在使用Oracle数据库时更为常见。 ### 问题描述 本文主要针对在Spring + MyBatis环境下,或使用Spring JDBC...
### Spring中事务的传播属性详解 #### 一、引言 在使用Spring框架进行应用程序开发时,事务管理是一项非常重要的特性。Spring提供了两种事务管理方式:编程式事务管理和声明式事务管理。其中,声明式事务管理因其...
例如,可以使用@Transactional注解在方法级别声明一个事务,该方法内的所有数据库操作将在同一个事务中执行。 文件名如"spring-jdbc-tran1"、"spring-jdbc-tran2"和"spring-jdbc-tran3"暗示了实验可能涉及Spring与...
在上面的配置文件中,我们可以看到 `<tx:advice>` 元素用于定义一个名为 "sgis.sdk.txAdvice" 的事务特性,该特性将所有以 "add*"、"delete*"、"update*" 开头的方法纳入事务管理中,并在出现异常时回滚事务。...
1. **开启事务**:在业务方法执行前,Spring会检查是否有事务注解(如@Transactional),如果有,就会开启一个新的事务。 2. **执行业务逻辑**:在事务内执行所有的数据库操作,如增删改查等。 3. **提交或回滚...
此外,Spring的事务传播行为(PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW等)是另一个重要概念,它定义了在一个事务中的方法如何启动新的事务或者加入到当前事务中。例如,PROPAGATION_REQUIRED表示如果当前...
这会告诉Spring在调用此方法时启动一个新的事务,并在方法正常结束时提交事务,或者在遇到异常时回滚事务。 4. 异常处理:为了触发事务回滚,方法内通常会抛出未检查异常(继承自`RuntimeException`的异常)或显式...
(2)(2) 在BookShopDao中添加一个purchase购书方法,其操作流程是获取书的单价->买书(更新库存)->更新账户余额,在BookShopDaoImp中实现该方法,并使用基于XML和Annotation的声明式事务管理来确保该购书过程能正常...
在数据库设计中,一对多关系很常见,比如一个用户可以有多个订单。在Ibatis中,可以通过配置XML映射文件来实现这种关系。我们可以在父表(如用户表)的映射文件中定义一个collection元素,指定关联的子表(如订单表...
Spring 声明式事务让我们从复杂的事务处理中得到解脱,使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的 try…catch…finally 代码。 事务...
Spring 声明式事务管理是Spring框架中的一个重要特性,它允许开发者在不编写任何事务管理代码的情况下,通过配置来管理事务。这种方式极大地简化了事务处理,并提高了代码的可维护性。以下是关于Spring声明式事务...
声明式事务管理的原理在于,当满足特定条件(如上述配置中的方法匹配)时,Spring 会自动开始、提交或回滚事务,无需在业务逻辑代码中显式调用`beginTransaction()`、`commit()`或`rollback()`等事务管理API。...
这种方法只需要在 Spring 配置文件中定义一个事务管理对象(如 DataSourceTransactionManager),然后加入 `<tx:annotation-driven/>` 节点,引用该事务管理对象,然后即可在需要进行事务处理的类和方法使用 `@...
当你在方法上使用`@Transactional(propagation = Propagation.NESTED)`时,Spring会在现有事务(如果有)中启动一个新的子事务。 2. **Savepoint**:在子事务开始时,Spring会自动创建一个保存点。如果子事务内部...
在需要事务控制的方法上添加这个注解,Spring会自动管理事务的开始、提交、回滚等操作。 2. 编程式事务管理: 编程式事务管理则是在代码中直接控制事务的开始、提交、回滚等操作,通常通过TransactionTemplate或...
在这个例子中,`createUser`方法会在一个事务中执行,如果发生异常,Spring会自动回滚事务,否则在方法正常结束时提交事务。 除了基本的事务控制,Spring还提供了丰富的事务属性,如传播行为(PROPAGATION_REQUIRED...