自定义注解简单实现
2019-05-26 15:49
453 查看
[code]package com.learn.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 事务注解 设置传播行为 /** * 在前面加个Ext * 这个注解是干嘛的 * 你们一定要知道 * 它是事务注解 * 定义好了之后 * 在这里面其实有这几个方法 * 但是我今天可能用不到这几个方法 * 你们下去自己去封装 * 设置传播行为 * 具体怎么实现呢 * 方法我就不写了 * 你们自己写 * 我们看看源码里面是怎么写的 * 你们看一下 * 源码里面加了拦截权限 * 把这些我们也copy过来 * 因为这个代码你们看的懂 * { ElementType.METHOD, ElementType.TYPE } * 我们可以写这两个 * 可以在方法上面加上这个注解 * 可以在类上加上这个注解 * 我们不允许在类上用 * 我们这个注解不允许在类上面用 * 只允许在方法上去玩了 * @Retention(RetentionPolicy.RUNTIME) * 这个写完之后我们再写第二步 * 跟着我的步骤来 * 封装手动事务 * 这个是我昨天写过的 * 是不是这样的 * 我写过的话就不写了 * 因为待会我们就会用到这段代码的 * * * * @author Leon.Sun * */ @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface ExtTransaction { }
[code]package com.learn.transaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.stereotype.Component; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.interceptor.DefaultTransactionAttribute; // 编程事务(需要手动begin 手动回滚 手都提交) /** * 我们还原成昨天的 * 否则到时会绕的 * 这个是手动获取事务 * 手动begin * 手动commit和手动rollback * 这代码你们有没有印象 * 昨天讲过的 * 我特意讲过这段代码的 * 还手写过这个事务的 * 是不是这样的 * 这个代码看不看得懂 * 这个代码不难 * 只要别人调用begin方法我就去开启一个事务 * 如果要是调用commit和rollback * 去回滚或者提交 * 现在看应该能够看得懂 * 这个昨天已经讲过的 * 这个其实没有什么难的 * 你们学过事务都知道的 * 然后我们接着再怎么做呢 * 我们核心是在具体如何扫包 * 具体如何扫包的话 * 那么这里面我不是要写一个AOP了 * * * * @author Leon.Sun * */ @Component //@Scope("prototype") // 每个事务都是新的实例 目的解决线程安全问题 多例子 public class TransactionUtils { // 全局接受事务状态 private TransactionStatus transactionStatus; // 获取事务源 @Autowired private DataSourceTransactionManager dataSourceTransactionManager; // 开启事务 public TransactionStatus begin() { transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); return transactionStatus; } // 提交事务 public void commit(TransactionStatus transaction) { dataSourceTransactionManager.commit(transaction); } // 回滚事务 public void rollback() { dataSourceTransactionManager.rollback(transactionStatus); } }
[code]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; // 自定义事务注解具体实现 /** * 我们自定义的事务注解具体实现 * 然后在这里写一下 * 加上切面编程@Aspect * 在这里面怎么写呢 * 在这里还要加上@Component * 让他注入到Spring的容器里面去 * 这步写完了之后 * 我说过的 * 你们说一下这是一个什么通知啊 * 就是这个拦截方法的时候 * 拦截所有方法的情况下 * 什么通知 * 你们想一想 * 就是这步他能用什么通知 * 肯定是环绕通知 * 记住肯定是环绕通知 * 不可能用到其他通知的 * 肯定是用环绕 * 那我把环绕代码copy过来好吧 * 我就不去写了 * 因为我昨天讲过了 * 是不是这样的 * 再写的话就比较浪费时间了 * 在这边说一下 * * * * @author Leon.Sun * */ @Aspect @Component public class AopExtTransaction { // 一个事务实例子 针对一个事务 /** * 我们把自定义的手动事务copy过来 * 再去@Autowired一下 * */ @Autowired private TransactionUtils transactionUtils; // 使用异常通知进行 回滚事务 /** * 我们现在是写框架的话 * 把它写成全部的 * "execution(* com.learn.service.*.*.*(..))" * 这是我要和你们去讲一下的 * 全部怎么写 * service.*.*.*(..) * 这个都理解吧 * 我就不去说了 * 我们找那个包下面的呢 * 我们找这个包下面的 * com.learn.service * 这步写完了之后 * 这边的代码就有点麻烦了 * 怎么麻烦了 * 这也是非常核心的代码 * * */ @AfterThrowing("execution(* com.learn.service.*.*.*(..))") public void afterThrowing() { // 获取当前事务进行回滚 // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); transactionUtils.rollback(); } // 环绕通知 在方法之前和之后处理事情 /** * 我们把这段代码copy过来 * 拦截到方法之后你们说一下 * 我这边就直接口说这个步骤 * 步骤答出来可能会好理解点 * 要不然直接这样改的话可能会比较绕 * 首先获取到代理对象的方法 * 第二步干嘛呢 * 获取该方法上是否加上注解 * 是不是这样的 * 然后到第三步的时候 * 你们想想到第三步怎么做 * 如果存在事务注解 * 是不是开启这个事务 * 然后到第四步干嘛 * 调用目标代理对象方法 * 到第五步怎么做你想想 * 第五步的时候代理对象方法调用完毕的情况下 * 他怎么做 * 想想怎么做 * 判断该方法上是否加上注解 * 这个我昨天已经说过了 * 然后同样道理 * 第六步什么样的呢 * 如果存在注解 * 你看我是写的非常详细的 * 如果存在注解 * 怎么样呢 * 是不是提交事务 * 我们可以先把四步先写出来 * 获取目标代理方法这个比较麻烦 * 大家写的时候可以直接去copy * 因为这里面的代码可能会比较多 * 然后你们不要看我们文档里面的 * 有些方法没有必要记下来 * 你只要知道怎么做就行了 * 这是我要和你们说的 * 所以这边我和你们说一下 * 这个你们不要去记 * * * * * @param pjp * @throws Throwable */ @Around("execution(* com.learn.service.*.*.*(..))") public void around(ProceedingJoinPoint pjp) throws Throwable { // 1.获取该方法上是否加上注解 ExtTransaction extTransaction = getMethodExtTransaction(pjp); /** * 我们拿到事务注解之后呢 * */ TransactionStatus transactionStatus = begin(extTransaction); // 2.调用目标代理对象方法 /** * 这个方法直接调用目标代理对象 * 待会我们的代码都会做重构 * */ pjp.proceed(); // 3.判断该方法上是否就上注解 commit(transactionStatus); } private TransactionStatus begin(ExtTransaction extTransaction) { if (extTransaction == null) { return null; } // 2.如果存在事务注解,开启事务 /** * 开启事务是不是到这里来了 */ return transactionUtils.begin(); } /** * 判断是否加上注解了 * 待会我会把整个代码做个重构 * 重构的话看起来就会舒服多了 * 大家先忍耐一下 * 做完了做重构 * 否则你们不知道重构是怎么来的 * 如果transactionStatus等于null说明了什么问题 * 你们想一想 * 我不需要给他开启事务 * 那我就不做任何操作 * * * @param transactionStatus */ private void commit(TransactionStatus transactionStatus) { /** * 所以判断不等于null的情况下 * 走到这一步的话 * 在方法上加上事务的注解了 * 是不是这样的 * 这个时候我怎么办 * transactionUtils.commit * */ if (transactionStatus != null) { /** * 5.如果存在注解,提交事务 * 去提交这样的一个事务 */ transactionUtils.commit(transactionStatus); } } // 获取方法上是否存在事务注解 /** * 这段代码直接copy过来 * 我先给你们写一下 * 因为这段代码比较长 * 而且写得话太浪费时间了 * 而且这段代码也没有什么意义 * 这段代码其实是怎么样的一个目的 * 给大家说一下 * 你们猜也猜得到干嘛用的呢 * 相当于通过你的切入点 * 获取目标代理对象方法 * 是不是这样的 * 我在下去写代码的时候 * 你知道我是怎么知道这API的吗 * 这也是你们要记住的思路 * 没有必要把任何代码都记住 * 什么意思呢 * 这段代码我开始也不知道通过这段代码可以获取代理对象的方法 * 我怎么做呢 * 先脑海中有这个思路 * 然后我直接百度去找 * AOP里面是怎么去获取代理对象的方法 * 就是这样的 * 明白这个意思没有 * 千万别说我下去把API记住 * 记一辈子没用的 * 我们写是写几个步骤核心的 * 这是我要给你们讲的 * 这理不理解 * 没必要记住 * 我之前自己下去找这个方法的时候 * 我会找很长时间的 * 那这个 3ff7 方法看不看得懂什么意思 * 获取你代理对象的方法 * 我把userServiceImpl的add给AOP进行管理的情况下 * 我们就可以去获取这个方法 * 这个都是能够看得懂的 * 如果这个看不懂那就说明有问题了 * 获取到之后 * 然后怎么做呢 * * * @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(); /** * 获取目标对象方法 */ Method objMethod = classTarget.getMethod(methodName, par); /** * 就是获取一下这个方法上有没有加上@ExtTransaction注解 * 是不是这样的 * 然后这个代码写完了之后呢 * 然后ExtTransaction.class * 然后我们这边拿到这个事务注解 * */ ExtTransaction extTransaction = objMethod.getDeclaredAnnotation(ExtTransaction.class); return extTransaction; } }
相关文章推荐
- Java自定义注解 简单Hibernate的注解实现
- 自定义注解实现--简单理解版
- 自定义注解的简单实现例子,附上代码和测试结果图
- 【Java】自定义注解 & 反射机制读取注解实现简单ORM
- 如何自定义注解实现简单的权限控制
- 一个简单的自定义注解的实现
- 一个简单的自定义注解的实现
- 通过自定义注解,实现简单的orm持久化类
- 基于AOP的自定义注解简单实现
- 自定义注解简单介绍及实现
- 简单实现自定义注解
- Java利用自定义注解、反射实现简单BaseDao实例
- 自定义注解+Struts2拦截器实现简单权限控制
- Java注解三 JUnit注解的简单实现
- 基于注解的spring AOP简单实现
- Flume自定义Source、Sink和Interceptor(简单功能实现)
- Spring 自定义注解实现操作日志记录功能
- 一起写框架-Ioc内核容器的实现-基础功能-组件注解支持自定义的对象名(九)
- 自定义线程池-c#的简单实现
- 基于spring注解切面的简单实现