目录
本章学习源码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子类代理)
- //后置通知业务接口
- public interface AfterReturningService {
- //我的名字
- String myName(String name);
- }
- //后置通知业务接口实现
- @Service //Spring的IOC注解式创建业务逻辑层实例
- public class AfterReturningServiceImpl implements AfterReturningService {
-
- @Override
- public String myName(String name) {
- System.out.println("AfterReturningServiceImpl中myName(String name)已执行...");
- return "我的姓名:" + name;
- }
- }
- @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());//全转为大写字母
- }
- }
- }
- }
- <?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>
- @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”,即验证了简单类型的返回值的不可变性。
- 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 +
- '}';
- }
- }
- //后置通知业务接口
- public interface AfterReturningService {
- //我的名字
- String myName(String name);
-
- //我的年龄
- People myAge(int age);
- }
- //后置通知业务接口实现
- @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);
- }
- }
- @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());
- }
- }
- }
- }
- @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了——>即验证了引用类型的返回值的可变性。
仅自己学习记录,如有错误,敬请谅解~,谢谢~~~