重构自定义注解代码

<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>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    	 http://www.springframework.org/schema/beans/spring-beans.xsd
     	 http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">

        
	<!-- aop的扫包注解是有的 -->
	<context:component-scan base-package="com.learn"></context:component-scan>
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day20"></property>
		<property name="user" value="root"></property>
		<property name="password" value="123456"></property>
	</bean>

	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 我们把原生的事务注解删掉 -->
	<!-- <tx:annotation-driven transaction-manager="dataSourceTransactionManager" /> -->
</beans>
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();
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值