• (Spring笔记)AspectJ最终通知——@After切面开发+切入点表达式取别名


    目录

    一、前言

    二、最终通知切面开发

            (1)最终通知业务接口

            (2)最终通知业务接口实现

            (3)最终通知切面类

            (4)applicationContext.xml配置文件

    三、junit代码测试

    四、切入点表达式取别名

            (1)修改最终通知业务接口实现——>去除异常

            (2)修改最终通知切面类——>取别名

            (3)junit代码测试不变动,运行效果——>观察切面执行顺序

    五、总结


    本章学习源码Github地址:https://github.com/GuiZhouAndroid/MySpringAllProject/tree/master/SpringDemo09_AspectJ/src/main/java/com/dhrj/java/zsitking/after


    一、前言

            在环绕通知中,如果发生异常,那么只有前切功能执行,后切功能因异常中断程序,因此后切功能无法正常执行。

            在后置通知中,如果发生异常,那么后切功能无法正常执行。

            在最终通知中无论目标方法是否正常执行(是否抛出异常),最终通知的代码(该切面增强的方法)都会被执行。——>作用类型于捕捉异常的finally


    二、最终通知切面开发

            (1)最终通知业务接口

    1. public interface AfterService {
    2. //我的信息
    3. String myInfo(String name, int age);
    4. }

            (2)最终通知业务接口实现

    1. @Service //Spring的IOC注解式创建业务逻辑层实例
    2. public class AfterServiceImpl implements AfterService {
    3. @Override
    4. public String myInfo(String name, int age) {
    5. System.out.println("myInfo(String name, int age)已执行...");
    6. System.out.println(1/0);//伪造异常,测试最终通知异常处理功能
    7. return "我的个人信息 = 姓名:" + name + ",年龄:" + age;
    8. }
    9. }

            (3)最终通知切面类

    1. @Aspect //交给AspectJ的框架去识别切面类
    2. @Component //切面实例注册加载到spring容器中
    3. public class AfterAspectJ {
    4. /**
    5. * 最终通知方法的规范
    6. * (1)访问权限是public
    7. * (2)方法没有返回值
    8. * (3)方法名称自定义
    9. * (4)方法没有参数,如果有也只能是JoinPoint
    10. * (5)使用@After注解表明是最终通知
    11. * 参数:value:指定切入点表达式
    12. */
    13. @After(value= "execution(* com.dhrj.java.zsitking.after.impl.AfterServiceImpl.*(..))")
    14. public void myAfter() {
    15. System.out.println("最终通知的功能...不论是否异常都会执行");
    16. }
    17. }

            (4)applicationContext.xml配置文件

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xmlns:aop="http://www.springframework.org/schema/aop"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    7. <!--基于注解的访问要添加包扫描-->
    8. <context:component-scan base-package="com.dhrj.java.zsitking.after"/>
    9. <!--业务实现绑定AOP,默认是JDK动态代理,取时必须使用接口类型-->
    10. <aop:aspectj-autoproxy/>
    11. </beans>

    三、junit代码测试

    1. @Test
    2. public void testAfter() {
    3. ApplicationContext ac = new ClassPathXmlApplicationContext("after/applicationContext.xml");
    4. AfterService afterService = (AfterService) ac.getBean("afterServiceImpl");
    5. System.out.println("后置通知绑定切面后的对象类型:" + afterService.getClass());
    6. System.out.println("最终返回值:"+afterService.myInfo("张松",24));
    7. }

            结论:异常会导致后置通知功能不执行,会导致环绕通知中的后切功能不执行。 


    四、切入点表达式取别名

            当较多的通知增强方法使用相同的execution切入点表达式时,编写、维护均较为麻烦。AspectJ提供了@Pointcut注解,用于定义execution切入点表达式。其用法是,将@Pointcut注解在一个方法之上,以后所有的execution的value 属性值均可使用该方法名作为切入点。代表的就是@Pointcut 定义的切入点。这个使用@Pointcut注解的方法一般使用private 的标识方法,即没有实际作用的方法。 

            如果多个切面切入到同一个切入点,可以使用别名简化开发。

            使用@Pointcut注解,创建一个空方法,此方法的名称就是别名。

            (1)修改最终通知业务接口实现——>去除异常

    1. @Service //Spring的IOC注解式创建业务逻辑层实例
    2. public class AfterServiceImpl implements AfterService {
    3. @Override
    4. public String myInfo(String name, int age) {
    5. System.out.println("myInfo(String name, int age)已执行...");
    6. //System.out.println(1/0);//伪造异常,测试最终通知异常处理功能
    7. return "我的个人信息 = 姓名:" + name + ",年龄:" + age;
    8. }
    9. }

            (2)修改最终通知切面类——>取别名

    1. @Aspect //交给AspectJ的框架去识别切面类
    2. @Component //切面实例注册加载到spring容器中
    3. public class AfterAspectJ {
    4. /**
    5. * 最终通知方法的规范
    6. * (1)访问权限是public
    7. * (2)方法没有返回值
    8. * (3)方法名称自定义
    9. * (4)方法没有参数,如果有也只能是JoinPoint
    10. * (5)使用@After注解表明是最终通知
    11. * 参数:value:指定切入点表达式
    12. */
    13. @After(value = "mycut()") //使用别名
    14. public void myAfter() {
    15. System.out.println("最终通知的功能...不论是否异常都会执行");
    16. }
    17. @Before(value = "mycut()") //使用别名
    18. public void myBefore() {
    19. System.out.println("前置通知的功能........");
    20. }
    21. @AfterReturning(value = "mycut()", returning = "obj") //使用别名
    22. public void myAfterReturning(Object obj) {
    23. System.out.println("后置通知的功能........");
    24. }
    25. @Around(value = "mycut()") //使用别名
    26. public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    27. System.out.println("环绕通知中的前置通知的功能........");
    28. Object obj = pjp.proceed(pjp.getArgs());
    29. System.out.println("环绕通知中的后置通知的功能........");
    30. return obj;
    31. }
    32. /**
    33. * 为这个切入点表示"execution(* com.dhrj.java.zsitking.after.impl.AfterServiceImpl.*(..))",取别名为“mycut”
    34. */
    35. @Pointcut(value = "execution(* com.dhrj.java.zsitking.after.impl.AfterServiceImpl.*(..))")
    36. public void mycut() {
    37. }
    38. }

            (3)junit代码测试不变动,运行效果——>观察切面执行顺序

     结论:(执行顺序按序号自上而下

            (1)最先执行环绕通知中的前置功能

            (2)再执行前置通知的切面方法

            (3)再执行环绕通知中的目标方法的业务功能

            (4)再执行后置通知的切面方法

            (5)再执行最终通知的切面方法

            (6)最先执行环绕通知中的后置功能

            (7)再return目标方法的返回值


    五、总结

    仅自己学习记录,如有错误,敬请谅解~,谢谢~~~

  • 相关阅读:
    linux下的io_uring和windows下的overlapped均可实现异步I/O,有什么异同?
    SonarQube安装
    Hyperledger Fabric 2.2 学习笔记:测试网络test-network
    面向6G的欠采样相移键控可见光调制方案
    【JavaScript】JQuery基础使用
    (数据科学学习手札146)geopandas中拓扑非法问题的发现、诊断与修复
    【Python面向对象进阶①】——给对象动态的增加属性和方法
    达人评测 锐龙r7 6800u和r5 6600h差距 r76800u和r56600h对比
    考研复试C语言篇
    【Linux】基础IO ——中
  • 原文地址:https://blog.csdn.net/qq_39038178/article/details/125545914