欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot项目中使用AOP的方法

程序员文章站 2024-01-21 14:13:52
本文介绍了springboot项目中使用aop的方法,分享给大家,具体如下: 1.概述 将通用的逻辑用aop技术实现可以极大的简化程序的编写,例如验签、鉴权等。sp...

本文介绍了springboot项目中使用aop的方法,分享给大家,具体如下:

1.概述

将通用的逻辑用aop技术实现可以极大的简化程序的编写,例如验签、鉴权等。spring的声明式事务也是通过aop技术实现的。

具体的代码参照 示例项目

spring的aop技术主要有4个核心概念:

pointcut: 切点,用于定义哪个方法会被拦截,例如 execution(* cn.springcamp.springaop.service.*.*(..))

advice: 拦截到方法后要执行的动作

aspect: 切面,把pointcut和advice组合在一起形成一个切面

join point: 在执行时pointcut的一个实例

weaver: 实现aop的框架,例如 aspectj 或 spring aop

2. 切点定义

常用的pointcut定义有 execution 和 @annotation 两种。execution 定义对方法无侵入,用于实现比较通用的切面。@annotation 可以作为注解加到特定的方法上,例如spring的transaction注解。

execution切点定义应该放在一个公共的类中,集中管理切点定义。

示例:

public class commonjoinpointconfig {
  @pointcut("execution(* cn.springcamp.springaop.service.*.*(..))")
  public void servicelayerexecution() {}
}

这样在具体的aspect类中可以通过 commonjoinpointconfig.servicelayerexecution()来引用切点。

public class beforeaspect {
  @before("commonjoinpointconfig.servicelayerexecution()")
  public void before(joinpoint joinpoint) {
    system.out.println(" -------------> before aspect ");
    system.out.println(" -------------> before execution of " + joinpoint);
  }
}

当切点需要改变时,只需修改commonjoinpointconfig类即可,不用修改每个aspect类。

3. 常用的切面

before: 在方法执行之前执行advice,常用于验签、鉴权等。

after: 在方法执行完成后执行,无论是执行成功还是抛出异常.

afterreturning: 仅在方法执行成功后执行.

afterthrowing: 仅在方法执抛出异常后执行.

一个简单的aspect:

@aspect
@component
public class beforeaspect {
  @before("commonjoinpointconfig.servicelayerexecution()")
  public void before(joinpoint joinpoint) {
    system.out.println(" -------------> before aspect ");
    system.out.println(" -------------> before execution of " + joinpoint);
  }
}

4. 自定义注解

假设我们想收集特定方法的执行时间,一种比较合理的方式是自定义一个注解,然后在需要收集执行时间的方法上加上这个注解。

首先定义一个注解tracktime:

@target({elementtype.method, elementtype.type})
@retention(retentionpolicy.runtime)
public @interface tracktime {
  string param() default "";
}

然后再定义一个aspect类,用于实现注解的行为:

@aspect
@component
public class tracktimeaspect {
  @around("@annotation(tracktime)")
  public object around(proceedingjoinpoint joinpoint, tracktime tracktime) throws throwable {
    object result = null;
    long starttime = system.currenttimemillis();
    result = joinpoint.proceed();
    long timetaken = system.currenttimemillis() - starttime;
    system.out.println(" -------------> time taken by " + joinpoint + " with param[" + tracktime.param() + "] is " + timetaken);
    return result;
  }
}

在某个方法上使用这个注解,就可以收集这个方法的执行时间:

@tracktime(param = "myservice")
public string runfoo() {
  system.out.println(" -------------> foo");
  return "foo";
}

注意 @tracktime(param = "myservice") 注解是可以传参的。

为了让注解可以传参数,需要在定义注解时指定一个参数string param() default "默认值",

同时在aspect类中,around方法上加上相应的参数,@around注解中也需要用参数的变量名tracktime,而不能用类名tracktime。

@around("@annotation(tracktime)")
public object around(proceedingjoinpoint joinpoint, tracktime tracktime)

5.总结

在运行示例项目时,控制台会输出以下内容:

 -------------> before aspect
 -------------> before execution of execution(string cn.springcamp.springaop.service.myservice.runfoo())
 -------------> foo
 -------------> time taken by execution(string cn.springcamp.springaop.service.myservice.runfoo()) with param[myservice] is 8
 -------------> after aspect
 -------------> after execution of execution(string cn.springcamp.springaop.service.myservice.runfoo())
 -------------> afterreturning aspect
 -------------> execution(string cn.springcamp.springaop.service.myservice.runfoo()) returned with value foo

可以看出几种 aspect 的执行顺序依次为 before after around afterreturning(afterthrowing)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。