• (Spring笔记)AspectJ后置通知——@AfterReturning切面开发


    目录

    一、前言 

    二、后置通知——>验证简单类型返回值不可变

            (1)后置通知业务接口

            (2)后置通知业务接口实现类

            (3)后置通知切面类

            (4)applicationContext.xml配置文件

            (5)junit代码测试

    三、后置通知——>验证引用类型返回值可变

            (1)新增实体类

            (2)修改后置通知业务接口

            (3)修改后置通知业务接口实现类

            (4)修改后置通知切面类

            (5)junit代码测试

    四、总结


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


    一、前言 

            重点:后置通知是在目标方法执行后切入切面功能,可以得到目标方法的返回值。如果目标方法的返回值是简单类型(8种基本类型+String)则不可改变,如果目标方法的返回值是引用类型可以改变——>根据返回值类型,决定是否具有资格重新改变目标方法执行之后最终接收的返回值。

            实现步骤

            (1)创建业务接口

            (2)创建业务实现

            (3)创建切面类,实现切面方法

            (4)在Spring的applicationContext.xml配置文件中进行切面绑定——>IOC+AspectJ内置代理模式(默认JDK动态代理+CGLib子类代理)


    二、后置通知——>验证简单类型返回值不可变

            (1)后置通知业务接口

    1. //后置通知业务接口
    2. public interface AfterReturningService {
    3. //我的名字
    4. String myName(String name);
    5. }

            (2)后置通知业务接口实现类

    1. //后置通知业务接口实现
    2. @Service //Spring的IOC注解式创建业务逻辑层实例
    3. public class AfterReturningServiceImpl implements AfterReturningService {
    4. @Override
    5. public String myName(String name) {
    6. System.out.println("AfterReturningServiceImpl中myName(String name)已执行...");
    7. return "我的姓名:" + name;
    8. }
    9. }

            (3)后置通知切面类

    1. @Aspect //交给AspectJ的框架去识别切面类
    2. @Component //切面实例注册加载到spring容器中
    3. public class AfterReturningAspectJ {
    4. /**
    5. * 后置通知的方法的规范
    6. * (1)访问权限是public
    7. * (2)方法没有返回值void
    8. * (3)方法名称自定义
    9. * (4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值
    10. * (5)使用@AfterReturning注解表明是后置通知
    11. * 参数:
    12. * value:指定切入点表达式
    13. * returning:指定目标方法的返回值的名称,则名称必须与切面方法的参数名称一致.
    14. */
    15. @AfterReturning(value = "execution(* com.dhrj.java.zsitking.afterreturn.impl.AfterReturningServiceImpl.*(..))", returning = "obj")
    16. //切面方法的注解
    17. public void myAfterReturningAspectJ(Object obj) {
    18. System.out.println("AspectJ后置通知已执行...在AfterReturningServiceImpl执行之后才执行");
    19. if (obj != null) { //判断目标方法的返回值是否为空
    20. if (obj instanceof String) { //判断目标方法返回值的引用是否指向String类型
    21. System.out.println("AspectJ后置通知接收返回值是字符串:" + ((String) obj).toUpperCase());//全转为大写字母
    22. }
    23. }
    24. }
    25. }

            (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.afterreturn"/>
    9. <!--业务实现绑定AOP,默认是JDK动态代理,取时必须使用接口类型-->
    10. <aop:aspectj-autoproxy/>
    11. </beans>

            (5)junit代码测试

    1. @Test
    2. public void testAfterReturning1() {
    3. ApplicationContext ac = new ClassPathXmlApplicationContext("afterreturn/applicationContext.xml");
    4. AfterReturningService afterReturningService = (AfterReturningService) ac.getBean("afterReturningServiceImpl");
    5. System.out.println("后置通知绑定切面后的对象类型:" + afterReturningService.getClass());
    6. System.out.println("最终返回值:"+afterReturningService.myName("ZhangSong"));
    7. }

            结论:由此可见,切面方法中已经是全部大小写的“ZHANGSONG”,根据后置通知特性“目标方法的返回值是简单类型(8种基本类型+String)则不可改变”——>最终结果输出原本的“ZhangSong”,即验证了简单类型的返回值的不可变性。


    三、后置通知——>验证引用类型返回值可变

            (1)新增实体类

    1. public class People {
    2. //年龄
    3. private int age;
    4. public People() {
    5. }
    6. public People(int age) {
    7. this.age = age;
    8. }
    9. public int getAge() {
    10. return age;
    11. }
    12. public void setAge(int age) {
    13. this.age = age;
    14. }
    15. @Override
    16. public String toString() {
    17. return "People{" +
    18. ", age=" + age +
    19. '}';
    20. }
    21. }

            (2)修改后置通知业务接口

    1. //后置通知业务接口
    2. public interface AfterReturningService {
    3. //我的名字
    4. String myName(String name);
    5. //我的年龄
    6. People myAge(int age);
    7. }

            (3)修改后置通知业务接口实现类

    1. //后置通知业务接口实现
    2. @Service //Spring的IOC注解式创建业务逻辑层实例
    3. public class AfterReturningServiceImpl implements AfterReturningService {
    4. @Override
    5. public String myName(String name) {
    6. System.out.println("AfterReturningServiceImpl中myName(String name)已执行...");
    7. return "我的姓名:" + name;
    8. }
    9. @Override
    10. public People myAge(int age) {
    11. System.out.println("AfterReturningServiceImpl中myAge(int age)已执行...");
    12. return new People(age);
    13. }
    14. }

            (4)修改后置通知切面类

    1. @Aspect //交给AspectJ的框架去识别切面类
    2. @Component //切面实例注册加载到spring容器中
    3. public class AfterReturningAspectJ {
    4. /**
    5. * 后置通知的方法的规范
    6. * (1)访问权限是public
    7. * (2)方法没有返回值void
    8. * (3)方法名称自定义
    9. * (4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值
    10. * (5)使用@AfterReturning注解表明是后置通知
    11. * 参数:
    12. * value:指定切入点表达式
    13. * returning:指定目标方法的返回值的名称,则名称必须与切面方法的参数名称一致.
    14. */
    15. @AfterReturning(value = "execution(* com.dhrj.java.zsitking.afterreturn.impl.AfterReturningServiceImpl.*(..))", returning = "obj")
    16. //切面方法的注解
    17. public void myAfterReturningAspectJ(Object obj) {
    18. System.out.println("AspectJ后置通知已执行...在AfterReturningServiceImpl执行之后才执行");
    19. if (obj != null) { //判断目标方法的返回值是否为空
    20. if (obj instanceof String) { //判断目标方法返回值的引用是否指向String类型
    21. System.out.println("AspectJ后置通知接收返回值是字符串:" + ((String) obj).toUpperCase());//全转为大写字母
    22. }
    23. if (obj instanceof People) { //判断目标方法返回值的引用是否指向People类型
    24. People people = (People) obj;
    25. people.setAge(100);
    26. System.out.println("AspectJ后置通知接收返回值是改变的People年龄:" + people.getAge());
    27. }
    28. }
    29. }
    30. }

            (5)junit代码测试

    1. @Test
    2. public void testAfterReturning2() {
    3. ApplicationContext ac = new ClassPathXmlApplicationContext("afterreturn/applicationContext.xml");
    4. AfterReturningService afterReturningService = (AfterReturningService) ac.getBean("afterReturningServiceImpl");
    5. System.out.println("后置通知绑定切面后的对象类型:" + afterReturningService.getClass());
    6. System.out.println("最终返回改变的People年龄:"+afterReturningService.myAge(24).getAge());
    7. }

             结论:由此可见,调用目标方法Peole myAge(int age)时。传入年龄值为24,经过后置通知切面功能后,已经动态的将目标方法Peole myAge(int age) 人的年龄值改变成100了——>即验证了引用类型的返回值的可变性


    四、总结

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

  • 相关阅读:
    目标检测YOLO实战应用案例100讲-基于锐化注意力的快速目标检测算法及其在遥感场景下的应用研究(中)
    maven assembly打包生成Java应用启动脚本bat和sh
    mysql数据900W+从17s到300ms是怎么做到的?sql优化的魅力(荣耀典藏版)
    [CISCN 2019 初赛]Love Math
    【深入理解设计模式】外观设计模式
    C#编程模式之原型模式
    写给技术人的管理入门知识1:什么是管理
    238.除自身以外数组的乘积
    华为机试真题 C++ 实现【执行时长】【GPU算力】
    uniapp x — 跨平台应用开发的强大助力
  • 原文地址:https://blog.csdn.net/qq_39038178/article/details/125541497