SpringBoot ---- AOP切面编程

252 阅读3分钟

AOP概念描述:

AOP(Aspect Oriented Programming),即面向切面编程(也叫面向方面编程,面向方法编程)。其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能。像日志记录,事务处理,权限控制等功能,都可以用AOP来“优雅”地实现,使这些额外功能和真正的业务逻辑分离开来,软件的结构将更加清晰。用我们自己的话描述在一整个过程中不影响任何业务逻辑的情况下增加一些前置或者后者的操作。

AOP中专业术语:

1.Advice 增强 表示在切入点想增加的功能,比如添加日志,包装参数。但是不仅仅只是增强功能代码,它还包含了方位信息。 方位信息包括方法前、方法后、方法环绕。 2.Pointcut 切点 顾名思义切点即表示你想在添加操作代码的位置,所以,一般我们要实现一个切点时,那么我们需要判断哪些连接点是符合我们的条件的,如:方法名是否匹配、类路径、以及子类等。 3.Joinpoint 连接点 连接点就是程序执行的某个特定的位置,比如:进方法之前,方法之后,某个特定的方法,或者满足指定的类路径等等。 4.Aspect 切面 切面由切点和增强实现。 5.Target 目标对象 即我们需要对其增强的业务,如果没有AOP,那么需要该业务类自己实现。 5.AOP proxy AOP代理 一个类被AOP织入后生成出了一个结果类,它是融合了原类和增强逻辑的代理类。 5.Weaving 织入 spring采用的事AspectJ编译期织入和类装载期织入。

废话不多说,直接上代码: pom.xml文件(springboot版本2.0.4.RELEASE)

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

类路径下的切面(指定controller目录下)

@Aspect
@Component
public class AopAspect {

    Logge LOG = LoggerFactory.getLogger(this.getClass());
    @Pointcut("execution(public * com.tom.controller..*(..))")
    public void addAdvice(){}

    @Around("addAdvice()")
    public Object  roundAdvice(ProceedingJoinPoint point) throws Throwable {
        long time =  (new Date()).getTime();

        String reqUrl ="";
        reqUrl = HttpKit.getRequest().getServletPath(); //获取前端请求接口的路径

        //获取拦截的方法名
        Signature sig = point.getSignature();
        MethodSignature msig = (MethodSignature) sig;

        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        String className = currentMethod.getName(); //获得请求的className

        Map<String, String> parameters = HttpKit.getRequestParameters(); //获取前端请求的参数

        LOG.info("请求时间:{},请求路径:{},方法名:{},参数:{},IP:{}",time,reqUrl,className,parameters,HttpKit.getIp());
        Object result = null;
        try{
            result = point.proceed();
        }catch (Exception e){
            LOG.info("方法请求错误:{},",e);
        }
        LOG.info("耗时:{},请求路径:{},方法名:{},返回参数:{},IP:{}",(new Date()).getTime() - time,reqUrl,className,result,HttpKit.getIp());
        return result;
    }
}

指定注解方法(只对有注解这个方法的进行切面编程)

 @Pointcut("@annotation(com.tom.aop_interface.AopFunction)")
    public void funAdvice(){}

AopFunction.class

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface AopFunction {

    String funcName() default "";

}

controller层代码实现

@RequestMapping("/hello_fun")
@AopFunction(funcName = "带注解方法名,需记录")
 public HashMap<String,Object> hello_fun(@RequestParam(required = false)HashMap map){...}

切面中获取自定义接口传参:
//获取操作名称 只对针对注解这个接口的有效
AopFunction annotation = currentMethod.getAnnotation(AopFunction.class);
String funName = annotation.funcName();

好了,主要实现就已经完成了,AOP切面是一个具有实际意义的面向对象编程,可以在工作中帮我们实现很多重复性的东西。