springAop面向切面

面向切面

1. 过程图示:

在这里插入图片描述

2. AOP有误异常时的执行顺序(@Around@Before@After@AfterReturning@AfterThrowing)

正常情况

  1. @Around start
  2. @Before…
  3. method invoke
  4. @Around end
  5. @After…
  6. @AfterReturning…

有异常的情况

  1. @Around start
  2. @Before…
  3. method invoke
  4. @After…
  5. @AfterThrowing…

整个执行过程

try{
    try{
        //@Around start
        //@Before
        method.invoke(..);
        //@Around end
    }finally{
        //@After
    }
    //@AfterReturning
}catch(){
    //@AfterThrowing
}

3. 使用介绍

1.@Pointcut(“execution(* com.test.server.impl…*(…))”),路径生效的方式

//界面生效的解释1execution(public * *(..))——表示匹配所有public方法
(2execution(* set*(..))——表示所有以“set”开头的方法
(3execution(* com.xyz.service.AccountService.*(..))——表示匹配所有AccountService接口的方法
(4execution(* com.xyz.service.*.*(..))——表示匹配service包下所有的方法
(5execution(* com.xyz.service..*.*(..))——表示匹配service包和它的子包下的方法

(1) 添加依赖

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

(2)相关通知的代码

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAop {
    //需要切入的类的所有的方法,具体的业务
    @Pointcut("execution(* com.test.server.impl..*(..))")
    public void pointcut() {
    }

    //前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("-----------before 方法执行了-----------");
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("前置方法中,获取参数: " + args[i]);
        }
        String name = joinPoint.getTarget().getClass().getName();
        System.out.println("前置方法中,获取目标类: " + name);
    }

    //后置通知
    @After("pointcut()")
    public void after() {
        System.out.println("-----------after 方法执行了-----------");
    }

    //返回通知
    @AfterReturning(pointcut = "pointcut()", returning = "rs")
    public void afterReturn(Object rs) {
        System.out.println("-----------afterReturning 方法执行了-----------");
        System.out.println("返回值为: " + rs);
    }

    //错误拦截通知
    @AfterThrowing(pointcut = "pointcut()", throwing = "err")
    public void afterTrowing(Throwable err) {
        System.out.println("-----------afterTrowing 统一错误处理执行了-----------");
        System.out.println("错误信息: " + err.getMessage());
    }

    //环绕通知
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        try {
            //around开始
            System.out.println("---around方法开始执行-----");
            //环绕通知,手动执行真正的业务方法
            Object proceed = joinPoint.proceed();
            //around结束
            System.out.println("----around方法执行完成----");

        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return null;
    }
}

2.注解生效的方式
(1).定义注解 @LogAnnotation

@Target(ElementType.METHOD)//标注在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface LogAnnotation{
}

(2)在需要增强的方法上添加定义的注解 @LogAnnotation

@Override
    @LogAnnotation
    public User findById(Integer id) {
        System.out.println("userService业务方法执行了");
        User user = userMapper.findById(id);
        return user;
    } 

(3)在通知的代码中,通过注解生效

@Pointcut("@annotation(com.test.config.LogAnnotation)")
public void pointcut() {
}

3.注解中传入参数

@Target(ElementType.METHOD)//标注在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface AopAnnotaiton {
String value() default "";
String decription() default "";
boolean flag() default true;
}

(2)在业务代码中添加定义的注解,并且给定参数

@Override
    @LogAnnotation(value = "test", description = "注解测试", flag = false)
    public User findById(Integer id) {
        System.out.println("userService业务方法执行了");
        User user = userMapper.findById(id);
        return user;
    }

(3)在通知的代码中,通过注解生效,并且获取注解

//前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("-----------before 方法执行了-----------");
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("前置方法中,获取参数: " + args[i]);
        }
        String name = joinPoint.getTarget().getClass().getName();
        System.out.println("前置方法中,获取目标类: " + name);

        //获取注解的参数
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        LogAnnotation logAnnotation = signature.getMethod().getDeclaredAnnotation(LogAnnotation.class);

        //获取注解中参数
        String value = logAnnotation.value();
        String description = logAnnotation.description();
        boolean flag = logAnnotation.flag();

        //输出
        System.out.println(value);
        System.out.println(description);
        System.out.println(flag);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值