<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.learn</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/javassist/javassist -->
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<!-- 引入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>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
</dependencies>
</project>
package com.learn.aop;
import java.lang.reflect.Method;
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 com.learn.annotation.ExtTransaction;
import com.learn.transaction.TransactionUtils;
@Aspect
@Component
public class AopExtTransaction {
// 一个事务实例子 针对一个事务
@Autowired
private TransactionUtils transactionUtils;
/**
* 使用异常通知进行回滚事务
* 是不是这样的
* 怎么做呢
* 在这里讲一下
* 这个代码昨天讲过的
* 怎么样做
* "execution(* com.learn.service.*.*.*(..))"
* 这个其实最好是定义一个公用的
* 然后记住就行了
* 可以这样做的
* 你们下去做优化
* 我们在这里怎么写呢
* 发生异常的情况下我是不是要做回滚
* 是不是这样的
*
*
*/
@AfterThrowing("execution(* com.learn.service.*.*.*(..))")
public void afterThrowing() {
// 获取当前事务进行回滚
/**
* 这个是什么呢
* 获取当前的事务进行回滚
* 我建议你们封装不要这么做
* 怎么做呢
* TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
* 你们最好不要使用这种方式
* 这种方式比较麻烦
*
*
*/
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
/**
* 判断下异常方法下是否有事务注解
* 如果有事务注解就进行回滚
* ThreadLocal也是可以解决共享问题
* 这个看你自己
*
*
*/
transactionUtils.rollback();
}
/**
* 这段代码是共享的
* 但是每个实例是不共享的
* 他们都是同一个transactionStatus
* 一个方法控制一个实例
* 就是这个意思
* 所以可能会比较绕了
*
*
* @param pjp
* @throws Throwable
*/
@Around("execution(* com.learn.service.*.*.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
ExtTransaction extTransaction = getMethodExtTransaction(pjp);
TransactionStatus transactionStatus = begin(extTransaction);
pjp.proceed();
commit(transactionStatus);
}
private TransactionStatus begin(ExtTransaction extTransaction) {
System.out.println("开启事务.......................");
if (extTransaction == null) {
return null;
}
return transactionUtils.begin();
}
private void commit(TransactionStatus transactionStatus) {
System.out.println("提交事务.......................");
if (transactionStatus != null) {
transactionUtils.commit(transactionStatus);
}
}
private ExtTransaction getMethodExtTransaction(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);
ExtTransaction extTransaction = objMethod.getDeclaredAnnotation(ExtTransaction.class);
return extTransaction;
}
}
package com.learn.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.learn.annotation.ExtTransaction;
import com.learn.dao.UserDao;
import com.learn.service.UserService;
import com.learn.transaction.TransactionUtils;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private TransactionUtils transactionUtils;
@Autowired
private UserDao userDao;
/**
* 这里加了一个事务注解
* 就开始事务
*
* 我们加自定义的注解@ExtTransaction
* 我们这里不要try
* 因为我们要演示一下异常场景
* 异常通知我们会单独讲的
* 上面加个注解
* 我们自己写的这个
* 我们怎么判断我们的这个事务到底有没有成功呢
* 只要执行到userDao.add("test001", 20);之后
* 不要插入到数据库里面去
* 是不是肯定是对的
* 是不是这样的
*
*
*/
// @Transactional
@ExtTransaction
public void add() {
userDao.add("test001", 20);
/**
* 这种情况下肯定是要回滚的
*
*/
int i = 1/0;
/**
* 到这里的时候数据是不是没有
* 看到没有
*
* 走过了之后是不是走完了
* 我们查一下有没有数据
* 没有吧
* 没有的话我们继续走
*
*
*/
System.out.println("####################################");
/**
* 走到这里
* 没有异常的情况下还是会回到AOP里面去
* 回到commit里面来
*
*
*/
userDao.add("test002", 21);
}
/**
* 这里没有加注解就不开启事务
* 那么最后怎么做呢
*
*
*
*
*/
public void del() {
System.out.println("del");
}
}
package com.learn.service;
//user 服务层
public interface UserService {
public void add();
public void del();
}
package com.learn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.learn.service.UserService;
public class Test001 {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
userService.add();
}
}