Springboot实现切面编程,获取方法名,参数,返回值等

2021-06-17 / 47 阅读 / Java
因为开发中偶尔会用到切面,常常因为要获取一个参数而烦恼,因此特意整理汇总了一个示例切面类

基本包含了所有的切面周期,能满足绝大部分应用需求,且各常用参数的获取方式都已直接给出

  1. 获取方法名

  2. 获取方法参数

  3. 获取返回值

  4. 获取对象

 

package ....aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 切面示例类.
 * <p>
 * @Pointcut定义切点 参考网上配置
 */
@Aspect
@Component
public class ExampleAspect {

    /**
     * 切入点定义.
     * <p>
     * 01.execution:一般用于指定方法的执行,用的最多。
     * 02.within:指定某些类型的全部方法执行,也可用来指定一个包。
     * 03.this:Spring Aop是基于动态代理的,生成的bean也是一个代理对象,this就是这个代理对象,当这个对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
     * 04.target:当被代理的对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
     * 05.args:当执行的方法的参数是指定类型时生效。
     * 06.@target:当代理的目标对象上拥有指定的注解时生效。
     * 07.@args:当执行的方法参数类型上拥有指定的注解时生效。
     * 08.@within:与@target类似,看官方文档和网上的说法都是@within只需要目标对象的类或者父类上有指定的注解,则@within会生效,而@target则是必须是目标对象的类上有指定的注解。而根据笔者的测试这两者都是只要目标类或父类上有指定的注解即可。
     * 09.@annotation:当执行的方法上拥有指定的注解时生效。
     * 10.reference pointcut:(经常使用)表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持
     * 11.bean:当调用的方法是指定的bean的方法时生效。(Spring AOP自己扩展支持的)
     */
    @Pointcut("execution(* *(..))")
    public void pointcut() {

    }

    /**
     * Around环绕通知:围绕整个周期,最优先执行.
     *
     * @param proceedingJoinPoint 环绕接入点
     * @return
     */
    @Around(value = "pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodInvocationProceedingJoinPoint joinPoint = (MethodInvocationProceedingJoinPoint) proceedingJoinPoint;
        // 目标对象
        Object target = joinPoint.getTarget();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 方法对象
        Method method = signature.getMethod();
        // 获取方法参数名称
        String[] argNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(method);
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        // 返回对象类型
        Class returnType = signature.getReturnType();
        return proceedingJoinPoint.proceed();
    }

    /**
     * Before前置通知:在目标方法执行前调用.
     *
     * @param joinPoint 接入点
     */
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
    }

    /**
     * After后置通知:无论目标方法在执行过程中出现异常都会在它之后调用.
     *
     * @param joinPoint 接入点
     */
    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
    }

    /**
     * After后置通知:在目标方法执行后无异常执行.
     */
    @AfterReturning(returning = "result", pointcut = "pointcut()")
    public void afterReturning(JoinPoint joinPoint, Object result) throws Throwable {
    }

    /**
     * AfterThrowing异常通知:在目标方法执行后有异常执行.
     *
     * @param joinPoint 接入点
     * @param exception 异常
     */
    @AfterThrowing(value = "pointcut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception) {
    }
}
相关推荐