思路:
- 自定义注解
- 写一个手动spring事务的类
- 使用AOP封装一个扫描包的类,并且使用拦截方法,判断是否方法含有注解
自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義 spring事務注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SelfAnnotation {
}
手动事务:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
@Component
@Scope("prototype")
public class TransactionUtils {
//全局事務狀態
private TransactionStatus transactionStatus;
//獲取事務源
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
// 开启事务
public TransactionStatus begin() {
System.out.println("开启事务");
transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transactionStatus;
}
// 提交事务
public void commit(TransactionStatus transaction) {
System.out.println("提交事务");
dataSourceTransactionManager.commit(transaction);
}
// 回滚事务
public void rollback() {
System.out.println("回滚事务...");
dataSourceTransactionManager.rollback(transactionStatus);
}
}
因为spring 是单例的,有线程安全问题,所以要加上 @Scope("prototype")
使用SpringAOP 的环绕 实现 扫描包和拦截判断是否有使用注解。
import annotation.SelfAnnotation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import transaction.TransactionUtils;
import java.lang.reflect.Method;
@Aspect
@Component
public class AopSelfTransaction {
//一个事务实例子 针对一个事务
@Autowired
private TransactionUtils transactionUtils;
// 使用异常通知进行 回滚事务
@AfterThrowing("execution(* service.*.*.*(..))")
public void afterThrowing() {
// 获取当前事务进行回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
transactionUtils.rollback();
}
// 环绕通知 在方法之前和之后处理事情
@Around("execution(* service.*.*.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
// 1.获取该方法上是否加上注解
SelfAnnotation selfAnnotation = getMethodSelfAnnotation(pjp);
TransactionStatus transactionStatus = begin(selfAnnotation);
// 2.调用目标代理对象方法
pjp.proceed();
// 3.判断该方法上是否就上注解
commit(transactionStatus);
}
private TransactionStatus begin(SelfAnnotation selfAnnotation) {
if (selfAnnotation == null) {
return null;
}
// 2.如果存在事务注解,开启事务
return transactionUtils.begin();
}
private void commit(TransactionStatus transactionStatus) {
if (transactionStatus != null) {
// 5.如果存在注解,提交事务
transactionUtils.commit(transactionStatus);
}
}
// 获取方法上是否存在事务注解
private SelfAnnotation getMethodSelfAnnotation(ProceedingJoinPoint pjp)
throws NoSuchMethodException, SecurityException {
String methodName = pjp.getSignature().getName();
// 获取目标对象
Class<?> classTarget = pjp.getTarget().getClass();
// 获取目标对象类型
Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
// 获取目标对象方法
Method objMethod = classTarget.getMethod(methodName, par);
SelfAnnotation selfAnnotation = objMethod.getDeclaredAnnotation(SelfAnnotation.class);
return selfAnnotation;
}
}
pom.xml
<dependencies>
<!-- 引入Spring-AOP等相关Jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency>
</dependencies>
spring.xml
<!-- 3.配置事务 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />