所有分类
  • 所有分类
  • 未分类

Spring之AOP-将类上的注解作为切点(用@Pointcut)

简介

说明

本文介绍Spring(SpringBoot)的AOP的用法:自定义注解,在Controller的类上使用此注解,然后在AOP中获得注解和方法的相关信息,并获取返回值信息。

本文使用@Pointcut+@Before+@AfterReturning。

方案介绍

AOP可将切点设为注解类,例如,若想控制Controller,只需切@RestController,方法有:

法1:@Pointcut结合@within(推荐)

@Pointcut("@within(org.springframework.web.bind.annotation.RestController)")

法2:@Before或@Around,结合@within

@Before("@within(restController)")
public void before(JoinPoint joinPoint, RestController restController)

基础代码

项目结构、pom.xml、公共代码等与此文一样:Spring之AOP-将方法上的注解做为切点(用@Before) – 自学精灵

测试

测试1:添加数据(有返回值)

后端结果

++++++++++++++++++++++++ before ++++++++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(User com.example.demo.controller.UserController.testAdd(User))
------------------ 方法信息 ------------------
joinPoint.getTarget().toString()  : com.example.demo.controller.UserController@1bc3bb5
methodSignature.getName()         : testAdd
method.getName()                  : testAdd
method.getReturnType().getName()  : com.example.demo.entity.User
------------------ 类的ApiLog注解数据 ------------------
tag: 用户接口
------------------ 类的Api注解数据 ------------------
tags:用户; value:
------------------ 方法注解数据 ----------------
操作为:添加数据
------------------ 入参数据 ------------------
User(id=12, userName=Tony, note=abc)
id是:12; 名字是:Tony; 备注是:abc
#################################################
+++++++++++++++++++++ afterReturning +++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(User com.example.demo.controller.UserController.testAdd(User))
------------------ 返回值 --------------------
{"id":12,"userName":"Tony","note":"abc"}
++++++++++++++++++++++++ after ++++++++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(User com.example.demo.controller.UserController.testAdd(User))

测试2:删除数据(无返回值)

后端结果:

++++++++++++++++++++++++ before ++++++++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(void com.example.demo.controller.UserController.delete(User))
------------------ 方法信息 ------------------
joinPoint.getTarget().toString()  : com.example.demo.controller.UserController@1bc3bb5
methodSignature.getName()         : delete
method.getName()                  : delete
method.getReturnType().getName()  : void
------------------ 类的ApiLog注解数据 ------------------
tag: 用户接口
------------------ 类的Api注解数据 ------------------
tags:用户; value:
------------------ 方法注解数据 ----------------
操作为:删除数据
------------------ 入参数据 ------------------
User(id=1212, userName=Peter, note=abc)
id是:1212; 名字是:Peter; 备注是:abc
#################################################
+++++++++++++++++++++ afterReturning +++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(void com.example.demo.controller.UserController.delete(User))
------------------ 返回值 --------------------
null
++++++++++++++++++++++++ after ++++++++++++++++++++++++++++++
------------------ joinPoint ------------------
execution(void com.example.demo.controller.UserController.delete(User))

AOP代码

写法1:不带参数

package com.example.demo.aspect;

import com.example.demo.annotation.ApiLog;
import com.example.demo.entity.User;
import com.example.demo.util.JsonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Before结合类上的注解获得操作日志
 */
@Aspect
@Component
public class ApiLogAspectByPointcutWithoutArg {
    @Pointcut("@within(com.example.demo.annotation.ApiLog)")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("++++++++++++++++++++++++ before ++++++++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("------------------ 方法信息 ------------------");
        System.out.println("joinPoint.getTarget().toString()  : " + joinPoint.getTarget().toString());
        System.out.println("methodSignature.getName()         : " + methodSignature.getName());
        System.out.println("method.getName()                  : " + method.getName());
        System.out.println("method.getReturnType().getName()  : " + method.getReturnType().getName());

        System.out.println("------------------ 类的ApiLog注解数据 ------------------");
        Class<?> declaringClass = method.getDeclaringClass();
        ApiLog apiLog = declaringClass.getAnnotation(ApiLog.class);
        System.out.println("tag: " + apiLog.tag());

        System.out.println("------------------ 类的Api注解数据 ------------------");
        Class<?> aClass = method.getDeclaringClass();
        if (aClass.isAnnotationPresent(Api.class)) {
            String[] tags = aClass.getAnnotation(Api.class).tags();
            String value = aClass.getAnnotation(Api.class).value();

            String tagJoin = String.join("+", tags);
            System.out.println("tags:" + tagJoin + "; value:" + value);
        }

        System.out.println("------------------ 方法注解数据 ----------------");
        if (method.isAnnotationPresent(ApiOperation.class)) {
            System.out.println("操作为:" + method.getAnnotation(ApiOperation.class).value());
        }

        System.out.println("------------------ 入参数据 ------------------");
        Object[] objects = joinPoint.getArgs();
        for (Object o : objects) {
            System.out.println(o);
            if (o instanceof User) {
                System.out.println("id是:" + ((User) (o)).getId() +
                        "; 名字是:" + ((User) (o)).getUserName() +
                        "; 备注是:" + ((User) (o)).getNote());
            }
        }
        System.out.println("#################################################");
    }

    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
        System.out.println("++++++++++++++++++++++++ after ++++++++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
    }

    @AfterReturning(value = "pointcut()", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, Object returnValue) {
        System.out.println("+++++++++++++++++++++ afterReturning +++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
        System.out.println("------------------ 返回值 --------------------");
        System.out.println(JsonUtil.toJson(returnValue));
    }

    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("+++++++++++++++++++++ afterThrowing +++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
        System.out.println("------------------ 异常信息 --------------------");
        e.printStackTrace();
    }
}

写法2:带参数

package com.example.demo.aspect;

import com.example.demo.annotation.ApiLog;
import com.example.demo.entity.User;
import com.example.demo.util.JsonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Before结合类上的注解获得操作日志
 */
@Aspect
@Component
public class ApiLogAspectByPointcutWithArg {
    @Pointcut("@within(apiLog)")
    public void pointcut(ApiLog apiLog) {

    }

    @Before("pointcut(apiLog)")
    // 会报警告:argNames attribute isn't defined。
    // 解决方法:@Before(value = "pointcut(apiLog)", argNames = "joinPoint,apiLog")
    public void before(JoinPoint joinPoint, ApiLog apiLog) {
        System.out.println("++++++++++++++++++++++++ before ++++++++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("------------------- 方法信息 ------------------");
        System.out.println("joinPoint.getTarget().toString()  : " + joinPoint.getTarget().toString());
        System.out.println("methodSignature.getName()         : " + methodSignature.getName());
        System.out.println("method.getName()                  : " + method.getName());
        System.out.println("method.getReturnType().getName()  : " + method.getReturnType().getName());

        System.out.println("------------------ 类的ApiLog注解数据 ------------------");
        System.out.println("tag: " + apiLog.tag());

        System.out.println("------------------ 类的Api注解数据 ------------------");
        Class<?> aClass = method.getDeclaringClass();
        if (aClass.isAnnotationPresent(Api.class)) {
            String[] tags = aClass.getAnnotation(Api.class).tags();
            String value = aClass.getAnnotation(Api.class).value();

            String tagJoin = String.join("+", tags);
            System.out.println("tags:" + tagJoin + "; value:" + value);
        }

        System.out.println("------------------ 方法注解数据 ----------------");
        if (method.isAnnotationPresent(ApiOperation.class)) {
            System.out.println("操作为:" + method.getAnnotation(ApiOperation.class).value());
        }

        System.out.println("------------------ 入参数据 ------------------");
        Object[] objects = joinPoint.getArgs();
        for (Object o : objects) {
            System.out.println(o);
            if (o instanceof User) {
                System.out.println("id是:" + ((User) (o)).getId() +
                        "; 名字是:" + ((User) (o)).getUserName() +
                        "; 备注是:" + ((User) (o)).getNote());
            }
        }
        System.out.println("#################################################");
    }

    @After("pointcut(apiLog)")
    // 会报警告:argNames attribute isn't defined。
    // 解决方法:@After(value = "pointcut(apiLog)", argNames = "joinPoint,apiLog")
    public void after(JoinPoint joinPoint, ApiLog apiLog) {
        System.out.println("++++++++++++++++++++++++ after ++++++++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
    }

    @AfterReturning(value = "pointcut(apiLog)", returning = "returnValue")
    // 会报警告:argNames attribute isn't defined。
    // 解决方法@AfterReturning(value = "pointcut(apiLog)", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, ApiLog apiLog, Object returnValue) {
        System.out.println("+++++++++++++++++++++ afterReturning +++++++++++++++++++++++++");
        System.out.println("------------------ joinPoint ------------------");
        System.out.println(joinPoint);
        System.out.println("-------------------- 返回值 -------------------");
        System.out.println(JsonUtil.toJson(returnValue));
    }
}

业务代码

package com.example.demo.controller;

import com.example.demo.annotation.ApiLog;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@ApiLog(tag = "用户接口")
@Api(tags = "用户")
@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @ApiOperation("打印数据")
    @GetMapping("print")
    public User testPrint(User user) {
        userService.printUser(user);
        return user;
    }

    @ApiOperation("添加数据")
    @PostMapping("add")
    @OperationLog(type = "添加", desc = "添加数据")
    public User testAdd(User user) {
        return user;
    }

    @ApiOperation("更新数据")
    @PostMapping("update")
    @OperationLog(type = "更新", desc = "更新数据")
    public User testUpdate(User user) {
        userService.printUser(user);
        return user;
    }

    @ApiOperation("删除数据")
    @PostMapping("delete")
    public void delete(User user) {
    }
}
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录