Java里使用AspectJ实现AOP

打印 上一主题 下一主题

主题 916|帖子 916|积分 2748

 前言已经正式从NET转型JAVA。今后开始多写一点JAVA相关的文章。
因为已经正式转Java了,所以,对于Java的一些判断,应该就比以前更准确了。总得来说,java有好的东西,有不好的东西,就语言本身和java的常用组件来讲,并不能判断,java比其他语言高一个档次,当然,也不会低一个档次。应该跟其他语言是一个段位的。
但java的调试,确实是比较花费时间,他做不到编译成功后,就能运行成功。这里有注解的问题,有maven的问题,有组件版本的问题。总之,检测的非常不好,非常浪费时间。
java的好处就是,团队成员比较多,毕竟开发起来真的很废人。但好处也在这里,人多,代表着,1,大家的压力都不大,人多压力就会分散。2,功能和性能有时间做的更优秀,人多就是工时多。
而且Java工资确实相对比其他语言高。
总体来说,java是比较幸福的。
开始正文

Aspectj提供一种在字符串里编程的模式,即在字符串里写函数,然后程序启动的时候会动态的把字符串里的函数给执行了。
例如:
  1. "execution(* *(..))"
复制代码
这里的execution就是一个函数,我们调用它,然后传递的参数是【* *(..)】。
Aspectj 使用 使用前,我们先了解一下execution和它的参数的匹配规则:
  1. execution: 用于匹配方法执行的连接点;
  2. execution(public * *(..)) ==> 匹配所有目标类的public方法,第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法。
  3. execution(* com.oysept.springboot.controller..*.*(..)) ==> 该包及所有子包下任何类的任何方法。
  4. execution(* com.oysept.springboot.controller.*(..)) ==> 该包下任何类的任何方法。
  5. execution(* com.oysept.springboot.controller.AspectJController.*(..)) ==> 该包下AspectJController类的任何方法。
  6. execution(* com..*.*Controller.method*(..)) ==> 匹配包名前缀为com的任何包下类名后缀为Controller的方法,方法名必须以method为前缀。
  7. execution(* *To(..)) ==> 匹配目标类所有以To为后缀的方法。
  8. 注: 该方法只是为了声明一个公共的环绕通知,也可以直接在具体方法配置,如: @Around("execution(* com.oysept.springboot.controller..*.*(..))")
复制代码
@Before和@AfterReturning

然后我们编写一个aspect的基础使用代码,如下:
  1. /**
  2. * @Before:定义了前置通知方法。打印出入参
  3. * @AfterReturning:定义了后置返回通知方法。打印出入参、返参
  4. */
  5. @Slf4j
  6. @Aspect
  7. @Component
  8. public class AopAspect_Basic {  
  9.     @Before("execution(public * com.k.tender.controller.business.user.UserController.*(..))")
  10.     public void doBefore(JoinPoint point){
  11.         String methodName = point.getSignature().getName();
  12.         List<Object> args = Arrays.asList(point.getArgs());
  13.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args);
  14.     }
  15.     @AfterReturning(value = "execution(public * com.k.tender.controller.business.user.UserController.*(..))", returning = "returnValue")
  16.     public void doAfterReturning(JoinPoint point, Object returnValue){
  17.         String methodName = point.getSignature().getName();
  18.         List<Object> args = Arrays.asList(point.getArgs());
  19.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args + ",返回值为:" + returnValue);
  20.     }
  21. }
复制代码
 如上代码,我们使用了@Before和@AfterReturning注解,在UserController调用前和后,分别埋了点,并输出了函数的入参和出参。
@Pointcut

@Pointcut其实是一个提取execution函数的操作,就是指定一个埋点,然后使用了@Before和@AfterReturning注解时,就不用每次都写那个execution函数了,这样就不用担心写错了。代码示例如下:
  1.   @Pointcut("execution(public * com.k.tender.controller.business.tender.TenderController.*(..))")
  2.     public void doPointCut() {
  3.     }
  4.     @Before("doPointCut()")
  5.     public void doBefore(JoinPoint point){
  6.         String methodName = point.getSignature().getName();
  7.         List<Object> args = Arrays.asList(point.getArgs());
  8.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args);
  9.     }
  10.     @AfterReturning(value = "doPointCut()", returning = "returnValue")
  11.     public void doAfterReturning(JoinPoint point, Object returnValue){
  12.         String methodName = point.getSignature().getName();
  13.         List<Object> args = Arrays.asList(point.getArgs());
  14.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args + ",返回值为:" + returnValue);
  15.     }
复制代码
对注解埋点

有时候,我们希望编写一个注解,然后让有该注解的函数,都被拦截,那么就可以使用Aspectj的注解埋点模式。
代码如下: 
  1. @Slf4j
  2. @Aspect
  3. @Component
  4. public class AopAspect_Annotation {
  5.     @Before("@annotation(com.k.tender.aop.MyAop)")
  6.     public void doBefore(JoinPoint point){
  7.         String methodName = point.getSignature().getName();
  8.         List<Object> args = Arrays.asList(point.getArgs());
  9.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args);
  10.     }
  11.     @AfterReturning(value ="@annotation(com.k.tender.aop.MyAop)", returning = "returnValue")
  12.     public void doAfterReturning(JoinPoint point, Object returnValue){
  13.         String methodName = point.getSignature().getName();
  14.         List<Object> args = Arrays.asList(point.getArgs());
  15.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args + ",返回值为:" + returnValue);
  16.     }
  17. }<br><br>
复制代码
public @interface MyAop {
      String value() default "自定义注解拦截";
}如果觉得写注解的命名空间麻烦,也可以这样写:
  1. @Before("@annotation(apiOperation)")
  2.     public void doBefore(JoinPoint point, MyAopAsyncTask apiOperation) {
  3.         String methodName = point.getSignature().getName();
  4.         List<Object> args = Arrays.asList(point.getArgs());
  5.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args);
  6.     }
复制代码
还可以将注解和前面的excution函数结合写:
  1.   @Before("execution(public * com.k..*.*(..)) && @annotation(apiOperation)")
  2.     public void doBefore(JoinPoint point, MyAopAsyncTask apiOperation) throws NoSuchMethodException {
  3.         String methodName = point.getSignature().getName();
  4.         List<Object> args = Arrays.asList(point.getArgs());
  5.         log.info("调用前连接点方法为:" + methodName + ",参数为:" + args);
  6.     }
复制代码
有时候我们的拦截会触发多次,这个具体原因调查起来很麻烦,我们也可以这样解决,代码如下:
  1. private volatile long hashcode = 0;//应对重复触发
  2.     @Before("execution(public * com.k..*.*(..)) && @annotation(apiOperation)")
  3.     public void doBefore(JoinPoint point, MyAopAsyncTask apiOperation) throws NoSuchMethodException {
  4.         if (hashcode != point.getTarget().hashCode()) {
  5.             log.info("========doBefore========");
  6.             ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  7.             HttpServletRequest request = requestAttributes.getRequest();
  8.             String method = request.getMethod();
  9.            
  10.         }
  11.     }
复制代码
使用hashcode来过滤多次拦截。
 ----------------------------------------------------------------------------------------------------
 到此,Android里使用AspectJ实现AOP就介绍完了。
----------------------------------------------------------------------------------------------------
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!
https://www.cnblogs.com/kiba/p/18027435
 
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表