解决事务线程安全问题

<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();
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值