重构自定义注解代码


  4.0.0
  com.learn
  demo
	0.0.1-SNAPSHOT
	
		
		
			javassist
			javassist
			3.12.1.GA
		
		
		
			org.springframework
			spring-core
			3.0.6.RELEASE
		
		
			org.springframework
			spring-context
			3.0.6.RELEASE
		
		
			org.springframework
			spring-aop
			3.0.6.RELEASE
		
		
			org.springframework
			spring-orm
			3.0.6.RELEASE
		
		
			org.aspectj
			aspectjrt
			1.6.1
		
		
			aspectj
			aspectjweaver
			1.5.3
		
		
			cglib
			cglib
			2.1_2
		

		
		
			com.mchange
			c3p0
			0.9.5.2
		
		
		
			mysql
			mysql-connector-java
			5.1.37
		
	



        
	
	
	 

	
		
		
		
		
	

	
		
	

	
		
	
	
	
	

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 com.learn.annotation.ExtTransaction;
import com.learn.transaction.TransactionUtils;

/**
 * 我们把代码重构一下
 * 要不然会比较麻烦
 * 
 * @author Leon.Sun
 *
 */
@Aspect
@Component
public class AopExtTransaction {
	// 一个事务实例子 针对一个事务
	@Autowired
	private TransactionUtils transactionUtils;

	// 使用异常通知进行 回滚事务
	/**
	 * 我们还有个异常通知没有封装完
	 * 异常我们要单独讲
	 * 所以我们先讲这个
	 * 
	 * 
	 */
	@AfterThrowing("execution(* com.learn.service.*.*.*(..))")
	public void afterThrowing() {
		// 获取当前事务进行回滚
		// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		transactionUtils.rollback();
	}

	// 环绕通知 在方法之前和之后处理事情
	/**
	 * 我们要把这段代码重构一下
	 * 所以这个时候我们怎么做呢
	 * 因为看那么长的代码我看起来也痛苦
	 * 这样的话我们就比较简单了
	 * 
	 * 我把所有的方法都给抽取出来
	 * 该比较舒服一点
	 * 有没有什么疑问
	 * 这应该没有什么疑问
	 * 是不是这样的
	 * 所以在这边讲一下
	 * 你们下去写代码的时候
	 * 就是别人看的时候也知道
	 * 获取这样的一个注解
	 * 然后进行begin
	 * 
	 * 
	 * 
	 * @param pjp
	 * @throws Throwable
	 */
	@Around("execution(* com.learn.service.*.*.*(..))")
	public void around(ProceedingJoinPoint pjp) throws Throwable {

		/**
		 * 1.获取该方法上是否加上注解
		 * 我们拿到事务注解
		 * 第一步获取目标代理对象
		 * 
		 * 首先进入到AOP代码里面去了
		 * 看到没有
		 * 进入到AOP代码里面去了之后
		 * 获取这个方法有没有加这个注解
		 * 
		 */
		ExtTransaction extTransaction = getMethodExtTransaction(pjp);
		/**
		 * 这边只要调用它就行了
		 * 看起来就轻松一点
		 * 然后把这个状态传进来
		 * 直接传入注解里面去
		 * 在这里我们是可以拿返回结果的
		 * 然后这边就是状态了
		 * 
		 * 有注解的时候我们在begin方法里面判断一下
		 * 判断一下他到底有没有这个注解
		 * 这个注解不等于null
		 * 不等于null的情况下
		 * 
		 * 开启完事务之后
		 * 
		 * 
		 */
		TransactionStatus transactionStatus = begin(extTransaction);
		// 2.调用目标代理对象方法
		/**
		 * 就会调用我们的目标代理对象方法
		 * 会走到我们的add方法里面来
		 * 
		 */
		pjp.proceed();
		// 3.判断该方法上是否就上注解
		/**
		 * 然后在这里就直接判断不等于null的情况下
		 * 然后整个我就封装的比较简单
		 * 我全部抽出来
		 * 不执行的情况就走异常通知的
		 * 大概就讲完了
		 * 有没有什么疑问呢
		 * 就这样封装完了
		 * 
		 * 是不是走commit
		 * 你的状态就不为空
		 * 走到里面去
		 * 不等于null的情况我就提交事务
		 * 
		 * 
		 */
		commit(transactionStatus);
	}

	/**
	 * 然后我再把它封装一下
	 * 这样看起来不是很爽
	 * 代码全部放在这里面去
	 * 其实这段代码也要封装一下
	 * 
	 * 
	 * 
	 * @param extTransaction
	 * @return
	 */
	private TransactionStatus begin(ExtTransaction extTransaction) {
		System.out.println("开启事务.......................");
		/**
		 * 没加事务就不会走到这里面去
		 * 就不会begin
		 * 也不会commit的
		 * 如果为null就直接return掉
		 * return null就行了
		 * 
		 * 走到这里判断一下
		 * 判断你有没有加注解
		 * 如果加了注解的情况下就开启这么一个事务
		 * 是不是这样的
		 * 你看一下
		 * 是不是开启事务
		 * 
		 * 
		 */
		if (extTransaction == null) {
			return null;
		}
		// 2.如果存在事务注解,开启事务
		/**
		 * 我喜欢这样去写
		 * 看着舒服一点
		 * 
		 * 不等于null就开启这个事务了
		 * 是不是这样的
		 * 
		 * 
		 */
		return transactionUtils.begin();
	}
	
	/**
	 * 把这个封装完
	 * 我就封装的比较加简单
	 * 尤其是写这样的代码
	 * 
	 * 
	 * @param transactionStatus
	 */
	private void commit(TransactionStatus transactionStatus) {
		System.out.println("提交事务.......................");
		/**
		 * 这里通过状态判断会好一点
		 * 如果transactionStatus不等于null的情况下
		 * 我再次提交这个事务
		 * 因为只有当他有状态的情况下
		 * 才有这样的一个权限
		 * 待会我们演示一把
		 * 只要transactionStatus他不为null的情况下
		 * 我才会提交
		 * 如果没有为空说明有事务
		 * 如果为空
		 * 那就根本没有走到里面去
		 * 在这里就直接走完就行了
		 * 没必要去提交事务了
		 * 是不是这样的
		 * 这段代码就大体的这样写了以后
		 * 这个时候我就说一下
		 * 因为之前我都是封装起来的
		 * 会有的
		 * 我待会演示就知道了
		 * 我待会讲你就知道
		 * 没加事务就不会走到这里面去
		 * 
		 */
		if (transactionStatus != null) {
			/**
			 * 如果他不等于null的情况下的时候
			 * 是不是这样的
			 * 
			 */
			transactionUtils.commit(transactionStatus);
		}

	}

	/**
	 * 我们定义一个方法
	 * 获取这个注解getMethodExtTransaction
	 * 获取方法上的一个注解
	 * 看有没有这个注解吗
	 * 我在上面写个注释
	 * 获取方法上是否存在事务注解
	 * 然后这里面怎么写呢
	 * 我们得重构过来
	 * 因为代码太多了
	 * 看起来比较痛苦
	 * 是不是同样要传入ProceedingJoinPoint切入点过来
	 * 是不是写完了
	 * 然后我们把异常抛出去
	 * 
	 * 
	 * 
	 * @param pjp
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 */
	private ExtTransaction getMethodExtTransaction(ProceedingJoinPoint pjp)
			throws NoSuchMethodException, SecurityException {
		String methodName = pjp.getSignature().getName();
		Class classTarget = pjp.getTarget().getClass();
		Class[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
		/**
		 * 我们看一下方法是哪一个
		 * 是不是add方法
		 * 
		 * 
		 */
		Method objMethod = classTarget.getMethod(methodName, par);
		/**
		 * 然后看一下add方法有没有注解
		 * 是不是有的
		 * 有没有加上注解
		 * 是没有没有提交
		 * 是不是有这样的一个注解
		 * 有这样的注解的话
		 * 
		 * 
		 */
		ExtTransaction extTransaction = objMethod.getDeclaredAnnotation(ExtTransaction.class);
		return extTransaction;
	}

}
package com.learn.service;

//user 服务层
public interface UserService {

	public void add();
	
	public void del();

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

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

}

 

你可能感兴趣的:(重构自定义注解代码)