(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)后置通知业务接口

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

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

//后置通知业务接口实现
@Service //Spring的IOC注解式创建业务逻辑层实例
public class AfterReturningServiceImpl implements AfterReturningService {

    @Override
    public String myName(String name) {
        System.out.println("AfterReturningServiceImpl中myName(String name)已执行...");
        return "我的姓名:" + name;
    }
}

        (3)后置通知切面类

@Aspect //交给AspectJ的框架去识别切面类
@Component //切面实例注册加载到spring容器中
public class AfterReturningAspectJ {

    /**
     * 后置通知的方法的规范
     * (1)访问权限是public
     * (2)方法没有返回值void
     * (3)方法名称自定义
     * (4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值
     * (5)使用@AfterReturning注解表明是后置通知
     * 参数:
     * value:指定切入点表达式
     * returning:指定目标方法的返回值的名称,则名称必须与切面方法的参数名称一致.
     */
    @AfterReturning(value = "execution(* com.dhrj.java.zsitking.afterreturn.impl.AfterReturningServiceImpl.*(..))", returning = "obj")
    //切面方法的注解
    public void myAfterReturningAspectJ(Object obj) {
        System.out.println("AspectJ后置通知已执行...在AfterReturningServiceImpl执行之后才执行");
        if (obj != null) { //判断目标方法的返回值是否为空
            if (obj instanceof String) { //判断目标方法返回值的引用是否指向String类型
                System.out.println("AspectJ后置通知接收返回值是字符串:" + ((String) obj).toUpperCase());//全转为大写字母
            }
        }
    }
}

        (4)applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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">

    <!--基于注解的访问要添加包扫描-->
    <context:component-scan base-package="com.dhrj.java.zsitking.afterreturn"/>
    <!--业务实现绑定AOP,默认是JDK动态代理,取时必须使用接口类型-->
    <aop:aspectj-autoproxy/>
</beans>

        (5)junit代码测试

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

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


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

        (1)新增实体类

public class People {
    //年龄
    private int age;

    public People() {
    }

    public People(int age) {
        this.age = age;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "People{" +
                ", age=" + age +
                '}';
    }
}

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

//后置通知业务接口
public interface AfterReturningService {
    //我的名字
    String myName(String name);

    //我的年龄
    People myAge(int age);
}

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

//后置通知业务接口实现
@Service //Spring的IOC注解式创建业务逻辑层实例
public class AfterReturningServiceImpl implements AfterReturningService {

    @Override
    public String myName(String name) {
        System.out.println("AfterReturningServiceImpl中myName(String name)已执行...");
        return "我的姓名:" + name;
    }

    @Override
    public People myAge(int age) {
        System.out.println("AfterReturningServiceImpl中myAge(int age)已执行...");
        return new People(age);
    }
}

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

@Aspect //交给AspectJ的框架去识别切面类
@Component //切面实例注册加载到spring容器中
public class AfterReturningAspectJ {

    /**
     * 后置通知的方法的规范
     * (1)访问权限是public
     * (2)方法没有返回值void
     * (3)方法名称自定义
     * (4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值
     * (5)使用@AfterReturning注解表明是后置通知
     * 参数:
     * value:指定切入点表达式
     * returning:指定目标方法的返回值的名称,则名称必须与切面方法的参数名称一致.
     */
    @AfterReturning(value = "execution(* com.dhrj.java.zsitking.afterreturn.impl.AfterReturningServiceImpl.*(..))", returning = "obj")
    //切面方法的注解
    public void myAfterReturningAspectJ(Object obj) {
        System.out.println("AspectJ后置通知已执行...在AfterReturningServiceImpl执行之后才执行");
        if (obj != null) { //判断目标方法的返回值是否为空
            if (obj instanceof String) { //判断目标方法返回值的引用是否指向String类型
                System.out.println("AspectJ后置通知接收返回值是字符串:" + ((String) obj).toUpperCase());//全转为大写字母
            }
            if (obj instanceof People) { //判断目标方法返回值的引用是否指向People类型
                People people = (People) obj;
                people.setAge(100);
                System.out.println("AspectJ后置通知接收返回值是改变的People年龄:" + people.getAge());
            }
        }
    }
}

        (5)junit代码测试

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

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


四、总结

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

电竞丶小松哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值