springboot AOP实战

AOP实战

maven依赖

引入aop的依赖

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

定义切面

采用扫描类的方式

将切点定义在AppService这个类的所有方法上

    @Pointcut("execution(public * com.lexiaoyao.aopdemo.service.AppService.*(..)))")
    public void BrokerAspect() {

    }

采用注解的方式

首先需要定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann {
    String value() default "";
}

然后定义切面

    @Pointcut("@annotation(com.lexiaoyao.aopdemo.Ann)")
    public void otherAspect() {

    }

通知

在通知执行和业务分离的逻辑

前置通知

在方法执行前执行

    @Before("BrokerAspect()")
    public void doBeforeGame(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Class<?> aClass = joinPoint.getTarget().getClass();
        System.out.println(aClass.getName());
        System.out.println(methodName);
        System.out.println("前置增强");
    }

后置通知

在方法执行后执行

    @After("BrokerAspect()")
    public void doAfterGame(JoinPoint joinPoint) {
        System.out.println("后置增强");
    }

返回通知

可获取方法的返回值,通过returning接受返回值

    @AfterReturning(value = "BrokerAspect()", returning = "returnValue")
    public void logMethodCall(JoinPoint jp, Object returnValue) throws Throwable {
        System.out.println("进入后置增强了!");

        String name = jp.getSignature().getName();
        System.out.println(name);
        Object[] args = jp.getArgs();
        for (Object arg : args) {
            System.out.println("参数:" + arg);
        }
        System.out.println("方法返回值为:" + returnValue);
    }

异常通知

在切面处捕获方法抛出的异常

    @AfterThrowing("BrokerAspect()")
    public void doAfterThrowingGame(JoinPoint joinPoint) {
        System.out.println("捕获异常");
    }

环绕通知

环绕通知的功能最强大,可以包含上述所有的通知。

    @Around("otherAspect()")
    public void doAroundGameData(ProceedingJoinPoint pjp) throws Throwable {
        try {
            Object[] args = pjp.getArgs();//获取参数
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            String name = signature.getMethod().getName();//获取方法名
            Ann declaredAnnotation = getDeclaredAnnotation(pjp);//获取注解
            System.out.println(declaredAnnotation.value());
            System.out.println(name);//前置增强
            Object proceed = pjp.proceed();//获取返回值
            System.out.println(proceed);//后置增强
        } catch (Throwable e) {
            //在切面里可以捕获切点抛出的异常
            System.out.println("异常通知");
        }
    }

JoinPoint

每个通知方法都可以放置JoinPoint变量。
JoinPoint是一个接口,常用两个实现类。

MethodInvocationProceedingJoinPoint是除了环绕通知的JoinPoint的实现类。‘
主要实现的方法为获取类名和方法名

        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 反射获取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();

ProceedingJoinPoint是环绕通知的JoinPoint实现类
通知方法中可以做任何的事情,当要将控制权交给被通知的方法时,需要调用ProceedingJoinPoint的proceed()方法。当你不调用proceed()方法时,将会阻塞被通知方法的访问。

获取切点处的注解

    public Ann getDeclaredAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 反射获`取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();
        // 拿到方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型(重载)获取到方法的具体信息
        Method objMethod = targetClass.getMethod(methodName, parameterTypes);
        // 拿到方法定义的注解信息
        Ann annotation = objMethod.getDeclaredAnnotation(Ann.class);
        // 返回
        return annotation;
    }

git

https://github.com/lexiaoyao1995/aopdemo

posted @ 2020-08-27 15:44  刃牙  阅读(324)  评论(0编辑  收藏  举报