spring是如何實現事務的 AOP + 動態代理
使用AOP攔截到我們加了@myAnnoTrancation的方法 然后開啟事務 使用動態代理調用當前方法 提交事務 同時使用AOP異常通知 做回滾的監聽
// 自定義注解
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnoTrancation {
}
// 事務管理
@Component
public class MyTransactionManager {
private TransactionStatus transactionStatus;
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
/**
* 開啟事務
*/
public TransactionStatus begin() {
TransactionStatus status = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return status;
}
/**
* 事務回滾
**/
public void rollBack() {
System.out.println("事務回滾");
dataSourceTransactionManager.rollback(transactionStatus);
}
/**
* 事務提交
* **/
public void commit(TransactionStatus transactionStatus) {
dataSourceTransactionManager.commit(transactionStatus);
}
}
//針對事務的攔截處理
@Aspect
@Component
@Transactional
public class MyAopTransaction {
@Autowired
private MyTransactionManager myTransactionManager;
TransactionStatus transactionStatus = null;
// ProceedingJoinPoint AOP獲取連接到對象
@Around("execution(* com.sunny.service.StudentService*.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("攔截起作用");
// 先獲取攔截的方法 判斷方法上有沒有@Transaction注解
MyAnnoTrancation myAnnoTrancation = geMyAnnoTrancation(point);
// 開啟事務
if (myAnnoTrancation != null) {
transactionStatus = myTransactionManager.begin();
}
// 調用攔截方法
Object proceed = point.proceed();
if (myAnnoTrancation != null) {
myTransactionManager.commit(transactionStatus);
}
point.getClass().getAnnotations();
return proceed;
}
/**
* 異常通知進行 回滾事務
*/
@AfterThrowing(throwing = "ex", pointcut = "execution(* com.sunny.service.StudentService*.*(..))")
public void afterThrowing(JoinPoint point, Throwable ex) {
System.out.println("異常捕獲" + ex.getMessage());
// 獲取當前事務 直接回滾
if (transactionStatus != null) {
myTransactionManager.rollBack();
}
}
// 獲取攔截對象釋放被打上 自定義注解
public MyAnnoTrancation geMyAnnoTrancation(ProceedingJoinPoint point) {
String methodName = point.getSignature().getName();
Class<? extends Object> classTarget = point.getTarget().getClass();
try {
Method method = classTarget.getMethod(methodName, classTarget.getClasses());
MyAnnoTrancation myannotation = method.getAnnotation(MyAnnoTrancation.class);
if (myannotation != null) {
return myannotation;
}
return null;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}