SpringBoot之AOP面向切面编程实例

目录

1.引入pom依赖

  • 主要是spring-boot-starter-aop依赖—>里面有需要的切面注解等配置


    <!--引入springboot父工程依赖-->
    <!--引入依赖作用:
    可以省去version标签来获得一些合理的默认配置
    -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <dependencies>
        <!--引入提供Web开发场景依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入面向切面依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

    </dependencies>


2.切入点表达式

——组成

  • 关键字(访问修饰符 返回值 包名.类名.方法名(参数)异常名)
  • 示例:execution(public String com.it.Controller.findById(int))
组成部分解释
关键字描述表达式的匹配模式(参看关键字列表)
访问修饰符方法的访问控制权限修饰符
类名方法所在的类(此处可以配置接口名称)
异常方法定义中指定抛出的异常


——逻辑运算符

运算符解释
&&连接两个切入点表达式,表示两个切入点表达式同时成立的匹配
||连接两个切入点表达式,表示两个切入点表达式成立任意一个的匹配
!连接单个切入点表达式,表示该切入点表达式不成立的匹配


——通配符

*示例:execution(public * com.it.*.UserService.find*(*))
*解释:匹配com.it包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

通配符解释
*单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

  • 实例: execution(public User com..UserService.findById(..))
  • 解释: 匹配com包下的任意包中的UserService类或接口中所有名称为findById并且返回是User实体的方法
通配符解释
..多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

  • 示例: execution(* *..*Service+.*(..))
  • 解释:匹配Service其子类方法
通配符解释
+专用于匹配子类类型


——范例

  • execution(* *(…))
  • execution(* (…))
  • execution(* .*(…))
  • execution(public * .*(…))
  • execution(public int .*(…))
  • execution(public void .*(…))
  • execution(public void com….(…))
  • execution(public void com…service..(…))
  • execution(public void com.it.service..(…))
  • execution(public void com.it.service.User*.*(…))
  • execution(public void com.it.service.Service.(…))
  • execution(public void com.it.service.UserService.*(…))
  • execution(public User com.it.service.UserService.find*(…))
  • execution(public User com.it.service.UserService.*Id(…))
  • execution(public User com.it.service.UserService.findById(…))
  • execution(public User com.it.service.UserService.findById(int))
  • execution(public User com.it.service.UserService.findById(int,int))
  • execution(public User com.it.service.UserService.findById(int,*))
  • execution(public User com.it.service.UserService.findById(*,int))
  • execution(public User com.it.service.UserService.findById())
  • execution(List com.it.service.*Service+.findAll(…))


3. 启动类配置

  • 只需要注意下 其它的类都要在启动类同包或及下层目录即可 让@SpringBootApplication中@ComponentScan扫描到;
  • 如果类不在同级目录或下层目录 可以用@Import(Xxx.class)引入;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/*
 * 面向切面编程Demo启动类
 * */
@SpringBootApplication
public class AOPTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(AOPTestApplication.class, args);
    }
}



4.通知类型

4.1 @Before : 标注当前方法作为前置通知

  • 前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
  • 应       用:数据校验

4.1.1 创建自定义注解(用于使用注解作为切入点)

  • 创建出名为BeforeDS 注解 作为后面的 before AOP切入点;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 自定义注解
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface BeforeDS {
    public String value() default "Before_Value";
}


4.1.2 设置切面类以及Before切面方法

  • @Aspect: 设置当前类为切面类
  • @Before("@annotation(com.it.mhh.anno.BeforeDS)")
           @Before:标注当前方法作为前置通知
           @annotation:指定用注解进行切面
           com.it.mhh.anno.BeforeDS:注解的全路径名
  • JoinPoint: 主要是获取切入点方法相应数据
          getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
          joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
          (MethodSignature) joinPoint.getSignature().getMethod().getAnnotation(BeforeDS.class) :获取切入点方法上的@BeforeDS注解
          …

import com.it.mhh.anno.AfterDS;
import com.it.mhh.anno.BeforeDS;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 通过业务代码动态切换数据源
 * 识别执行方法上得注解
 */
@Component
@Aspect //设置当前类为切面类
//设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
@Order(0)
public class SwitchDSAspect {
    

       /**
     * 标注当前方法作为前置通知
     */
    @Before("@annotation(com.it.mhh.anno.BeforeDS)")//用自定义注解 BeforeDS 作为切入点
    public void before(JoinPoint joinPoint) throws Throwable {
        Signature pointSignature = joinPoint.getSignature();
        System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:"+pointSignature);
        
        Object[] args = joinPoint.getArgs();
        System.err.println("切入点方法的参数列表-->:"+ Arrays.toString(args));
        
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        BeforeDS beforeDS = method.getAnnotation(BeforeDS.class);
        String value = beforeDS.value();//获取切入点方法上BeforeDS注解的值
        System.err.println("切面类中before方法--自定义注解BeforeDS中的值为-->:" + value);
    }


}


4.1.3 @Before : 标注当前方法作为前置通知测试


4.1.3.1 Controller层
import com.it.mhh.anno.AfterDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("AOPtest")
public class AOPTestController {

    @Value("#{AOPTestServiceImpl}")
    private AOPTestService aopTestService;

    @RequestMapping("before")
    public String beforeTest() {
        System.out.println("before测试-controller");
        return aopTestService.beforeTest();
    }
    
}


4.1.3.2 service层
public interface AOPTestService {
    String beforeTest();
}


4.1.3.3 serviceimpl层
import com.it.mhh.anno.BeforeDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.stereotype.Service;

@Service
public class AOPTestServiceImpl implements AOPTestService {


    @BeforeDS //使用自定义注解 执行切面
    @Override
    public String beforeTest() {
        System.out.println("before测试-serviceimpl层");
        return "before测试end";
    }
    
}



@Before标注当前方法作为前置通知测试结果:
  • 首先可以看出先走了controller层并打印了日志,我在serviceimp层的方法上加入了自定义注解, 此注解作为切入点那么就会走设置的切入点方法,执行完切入点方法后执行后面代码;
  • 此方法没有入参 所以参数列表为空;
  • BeforeDS注解没有设置值,所以是默认值

在这里插入图片描述
在这里插入图片描述



4.2 @After : 标注当前方法作为后置通知

  • 后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
  • 应       用:现场清理

4.2.1 创建自定义注解(用于使用注解作为切入点)

  • 创建出名为AfterDS 注解 作为后面的 after AOP切入点;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
 * 自定义注解
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterDS {
    public String value() default "After_Value";
}


4.2.2 设置切面类以及After切面方法

  • @Aspect: 设置当前类为切面类
  • @After("@annotation(afterDS)")
           @After:标注当前方法作为后置通知
           @annotation:指定用注解进行切面
           afterDS:切面方法上的入参注解名
  • JoinPoint: 主要是获取切入点方法相应数据
          getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
          joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
          …

import com.it.mhh.anno.AfterDS;
import com.it.mhh.anno.BeforeDS;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 通过业务代码动态切换数据源
 * 识别执行方法上得注解
 */
@Component
@Aspect //设置当前类为切面类
//设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
@Order(0)
public class SwitchDSAspect {
    
    /*
     * 标注当前方法作为后置通知
     * */
    @After("@annotation(afterDS)") //用自定义注解 AfterDS 作为切入点
    public void after(JoinPoint joinPoint, AfterDS afterDS) {
        Signature pointSignature = joinPoint.getSignature();
        System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);

        Object[] args = joinPoint.getArgs();
        System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));

        String value = afterDS.value();
        System.err.println("切面类中after方法--自定义注解中的值为->" + value);

    }

}


4.2.3 @After : 标注当前方法作为后置通知测试


4.2.3.1 Controller层
import com.it.mhh.anno.AfterDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("AOPtest")
public class AOPTestController {

    @Value("#{AOPTestServiceImpl}")
    private AOPTestService aopTestService;

    @AfterDS("afterController")
    @PostMapping("after/{name}")
    public String afterTest(@PathVariable("name") String name) {
        System.out.println("after测试-controller");
        return aopTestService.afterTest(name);
    }
    
}


4.2.3.2 service层
public interface AOPTestService {
   String afterTest(String name);
}


4.2.3.3 serviceimpl层
import com.it.mhh.anno.BeforeDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.stereotype.Service;

@Service
public class AOPTestServiceImpl implements AOPTestService {


    @Override
    public String afterTest(String name) {
        System.out.println("after测试-serviceimpl层");
        return "afterTest测试end--入参姓名-->:"+name;
    }
    
}



@After : 标注当前方法作为后置通知 测试结果:
  • 首先可以看出在controller层的方法上加入了自定义注解@AfterDS(afterController),然后代码走了controller层并打印了日志,也走完了serviceimp层的方法以及打印了日志, 之后执行了切入点方法的代码;
  • 此方法有一个入参 所以参数列表中有一个值;
    @AlterDS()设置了value值 所以打印的就是设置的值

在这里插入图片描述
在这里插入图片描述



4.3 @Around: 标注当前方法作为环绕通知

  • 环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行
  • 应       用:十分强大,可以做任何事情

4.3.1 设置切面类以及@Around切面方法

  • @Aspect: 设置当前类为切面类
  • @Around(“pointCut()”)------>@Pointcut(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.pointCutTest())”)
           @Around:标注当前方法作为环绕通知
           pointCut():自定义的方法,此方法上有一个注解 @Pointcut()
           @Pointcut():此注解的value值为切入点表达式
  • JoinPoint: 主要是获取切入点方法相应数据
          getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
          joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
           ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
          …

import com.it.mhh.anno.AfterDS;
import com.it.mhh.anno.BeforeDS;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 通过业务代码动态切换数据源
 * 识别执行方法上得注解
 */
@Component
@Aspect //设置当前类为切面类
//设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
@Order(0)
public class SwitchDSAspect {
    
    //    @Pointcut(value = "@annotation(com.it.mhh.anno.DS)")
    @Pointcut(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.pointCutTest())")
    public void pointCut() {
    }
  /*
     *标注当前方法作为环绕通知
     * */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取执行签名信息
        Signature signature = joinPoint.getSignature();
        //通过签名获取执行类型(接口名)
        String targetClass = signature.getDeclaringTypeName();
        //通过签名获取执行操作名称(方法名)
        String targetMethod = signature.getName();
        //获取操作前系统时间beginTime
        long beginTime = System.currentTimeMillis();
        //消息入参joinPoint.getArgs() 及执行结束 反参ret 之后return到请求页面
        System.err.println("环绕通知在此方法之前执行的代码");
        Object ret = joinPoint.proceed(joinPoint.getArgs());
        System.err.println("环绕通知在此方法之后执行的代码");
        //获取操作后系统时间endTime
        long endTime = System.currentTimeMillis();
        System.err.println(targetClass + " 中 " + targetMethod + " 运行时长 " + (endTime - beginTime) + "ms");


        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Annotation[] annotations = method.getAnnotations();
        System.err.println("此方法上的所以注解:"+ Arrays.toString(annotations));


        System.err.println("真实反参--》"+ret);
        //这里可以修改返回数据
        return ret+"--》:通过环绕通知修改的参数";
    }

}


4.3.2 @Around : 标注当前方法作为环绕通知测试


4.3.2.1 Controller层
import com.it.mhh.anno.AfterDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("AOPtest")
public class AOPTestController {

    @Value("#{AOPTestServiceImpl}")
    private AOPTestService aopTestService;

    @PostMapping("pointCut")
    public String pointCutTest() {
        System.out.println("pointCutTest测试-controller");
        return aopTestService.pointCutTest();
    }
    
}


4.3.2.2 service层
public interface AOPTestService {
   String pointCutTest();
}


4.3.2.3 serviceimpl层
import com.it.mhh.anno.BeforeDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.stereotype.Service;

@Service
public class AOPTestServiceImpl implements AOPTestService {


    @Override
    @Order
    public String pointCutTest() {
        System.out.println("pointCutTest测试-serviceimpl层");
        return "pointCutTest测试end";
    }
    
}



@Around : 标注当前方法作为环绕通知 测试结果:
  • @Around环绕通知可以修改返回参数
  • 切入点为AOPTestServiceImpl类pointCutTest()方法
    所以首先走了controller并打印日志 然后到了pointCutTest()方法 在此方法之前走了环绕通知方法的joinPoint.proceed(joinPoint.getArgs())代码之前的编码,然后接着走AOPTestServiceImpl类pointCutTest()方法里的代码,走完后会回到环绕通知的代码并执行完后返回结束;
  • method.getAnnotations():这里 好像发现获取方法上的注解 获取不到@Override

在这里插入图片描述


在这里插入图片描述



4.4 @AfterReturning: 标注当前方法作为返回后通知

  • 返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
  • 应       用:返回值相关数据处理

4.4.1 设置切面类以及@AfterReturning切面方法

  • @Aspect: 设置当前类为切面类
  • @AfterReturning(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterReturningTest(int ,int ))”, returning = “result”)
           @AfterReturning:标注当前方法作为返回后通知
           execution:切入点表达式—匹配执行指定方法
           returning:设定使用通知方法参数接收返回值的变量名
  • JoinPoint: 主要是获取切入点方法相应数据
          getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
          joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
           ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
          …

import com.it.mhh.anno.AfterDS;
import com.it.mhh.anno.BeforeDS;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 通过业务代码动态切换数据源
 * 识别执行方法上得注解
 */
@Component
@Aspect //设置当前类为切面类
//设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
@Order(0)
public class SwitchDSAspect {
    
      /*
     *  标注当前方法作为返回后通知
     *
     * 当连接点方法成功执行后,返回通知方法才会执行,如果连接点方法出现异常,则返回通知方法不执行。
     * 返回通知方法在目标方法执行成功后才会执行,所以,返回通知方法可以拿到目标方法(连接点方法)执行后的结果。
     * */
    //returning :设定使用通知方法参数接收返回值的变量名
    @AfterReturning(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterReturningTest(int ,int ))", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        Signature pointSignature = joinPoint.getSignature();
        System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);

        Object[] args = joinPoint.getArgs();
        System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));

        System.err.println("切入点返回参-->:"+result);
    }
}


4.4.2 @AfterReturning: 标注当前方法作为返回后通知测试


4.4.2.1 Controller层
import com.it.mhh.anno.AfterDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("AOPtest")
public class AOPTestController {

    @Value("#{AOPTestServiceImpl}")
    private AOPTestService aopTestService;

    @PostMapping("afterReturning/{i1}/{i2}")
    public String afterReturningTest(@PathVariable("i1") int i1, @PathVariable("i2") int i2) {
        System.out.println("afterReturningTest测试-controller");
        return aopTestService.afterReturningTest(i1, i2);
    }
    
}


4.4.2.2 service层
public interface AOPTestService {
       String afterReturningTest(int i1, int i2);
}


4.4.2.3 serviceimpl层
import com.it.mhh.anno.BeforeDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.stereotype.Service;

@Service
public class AOPTestServiceImpl implements AOPTestService {


    @Override
    public String afterReturningTest(int i1, int i2) {
        System.out.println("afterReturningTest测试-serviceimpl层");
        return "afterReturningTest测试end--->int总和:" + (i1 + i2);
    }
    
}



@AfterReturning : 标注当前方法作为返回后通知 测试结果:
  • 原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
  • 切入点为AOPTestServiceImpl类afterReturningTest(int ,int )方法

在这里插入图片描述


在这里插入图片描述



4.5 @AfterThrowing: 标注当前方法作为抛出异常后通知

  • 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
  • 应       用:对原始方法中出现的异常信息进行处理

4.5.1 设置切面类以及@AfterThrowing切面方法

  • @Aspect: 设置当前类为切面类
  • @AfterThrowing(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterThrowingTest(String))”, throwing = “e”)
           @AfterThrowing:标注当前方法作为抛出异常后通知
           execution:切入点表达式—匹配执行指定方法
           throwing:设定使用通知方法参数接收原始方法中抛出的异常对象名
  • JoinPoint: 主要是获取切入点方法相应数据
          getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
          joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
           ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
          …

import com.it.mhh.anno.AfterDS;
import com.it.mhh.anno.BeforeDS;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 通过业务代码动态切换数据源
 * 识别执行方法上得注解
 */
@Component
@Aspect //设置当前类为切面类
//设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
@Order(0)
public class SwitchDSAspect {
    
    /*
     * 标注当前方法作为异常后通知
     * 异常通知方法只在连接点方法出现异常后才会执行,否则不执行。
     * 在异常通知方法中可以获取连接点方法出现的异常。在切面类中异常通知方法
     * */
    //throwing :设定使用通知方法参数接收原始方法中抛出的异常对象名
    @AfterThrowing(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterThrowingTest(String))", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e) {
        Signature pointSignature = joinPoint.getSignature();
        System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);

        Object[] args = joinPoint.getArgs();
        System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));

        System.err.println("切入点异常-->:" + e);
    }
}


4.5.2 @AfterThrowing: 标注当前方法作为异常后通知测试


4.5.2.1 Controller层
import com.it.mhh.anno.AfterDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("AOPtest")
public class AOPTestController {

    @Value("#{AOPTestServiceImpl}")
    private AOPTestService aopTestService;

    @PostMapping("afterThrowing/{string}")
    public String afterThrowingTest(@PathVariable("string") String string) {
        System.out.println("afterThrowingTest测试-controller");
        return aopTestService.afterThrowingTest(string);
    }
    
}


4.5.2.2 service层
public interface AOPTestService {
       String afterThrowingTest(String string);
}


4.5.2.3 serviceimpl层
import com.it.mhh.anno.BeforeDS;
import com.it.mhh.service.AOPTestService;
import org.springframework.stereotype.Service;

@Service
public class AOPTestServiceImpl implements AOPTestService {


    @Override
    public String afterThrowingTest(String string) {
        System.out.println("afterThrowingTest测试-serviceimpl层");
        int i = 1 / 0;
        return "afterThrowingTest测试end--->String值:" + string;
    }
    
}



@AfterThrowing: 标注当前方法作为异常后通知 测试结果:
  • 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
  • 切入点为AOPTestServiceImpl类afterThrowingTest(String)方法

在这里插入图片描述


在这里插入图片描述









链接:SpringBoot之AOP面向切面编程实例 源代码下载地址

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟浩浩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值