Spring框架学习笔记——面向切面编程(5)

@Afterreturning后置通知注解的使用

1.创建目标类:接口和他的实现类:

package com.wxx.ba02;

public interface SomeService {
    void doSome(String name,Integer age);
    String doOther(String name,Integer age);
    Student doOther2(String name,Integer age);
}

package com.wxx.ba02;

//目标类
public class SomeServiceImpl implements SomeService {
    @Override

    public void doSome(String name,Integer age) {
        System.out.println("===目标方法doSome()===");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====目标方法doOther===");
        return "abcd";
    }

    @Override
    public Student doOther2(String name,Integer age){
        System.out.println("====目标方法doOther2===");
        Student student=new Student();
        student.setName(name);
        student.setAge(age);
        return student;
    }
}

2.创建切面类:

package com.wxx.ba02;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.Date;

/*
    @Aspect:是aspectj框架中的注解
    作用:表示当前类是切面类。
    切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
    位置:在类定义的上面
*/
@Aspect
public class MyAspect {
    /*
     * 后置通知定义方法,方法是实现切面功能的。
     * 方法的定义要求:
     * 1.公共方法 public
     * 2.方法没有返回值
     * 3.方法名称自定义
     * 4.方法可以有参数,推荐Object,参数名自定义
     * */


    /*
     * @AfterReturning:后置通知
     *   属性:1.value 切入点表达式
     *       2.returning 自定义变量,表示目标方法的返回值
     *       自定义变量名必须和通知方法的形参名一样。
     *   位置:方法定义的上面
     *   特点:
     *   1.在目标方法之后执行
     *   2.能够获取到目标方法的返回值,可以根据返回值做不同的处理概念
     *       object res =doOther();
     * 3.可以修改返回值
     *
     *   后置通知的执行
     *   先Object res=doOther();
     *   然后myAfterReturning(res);
     *
     * */
    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "res")
    public void myAfterReturning(Object res){
        //Object res:是目标方法执行后的返回值,根据返回值做切面功能处理
        System.out.println("后置通知:在目标方法之后执行,获取的返回值是:"+res);
        if("abcd".equals(res)){
            res="dcba";
        }else {
            //做一些其他工作
        }
        System.out.println("后置通知:在目标方法之后执行,获取的返回值是:"+res);
    }

    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther2(..))",returning = "res")
    public void myAfterReturning2(Object res){
        //Object res:是目标方法执行后的返回值,根据返回值做切面功能处理
        Student student=(Student)res;
        student.setName("王二");
        student.setAge(11);

    }


}

3.编写测试类:

package com.wxx;

import com.wxx.ba02.SomeService;
import com.wxx.ba02.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest02 {

    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
        //从容器中获取目标对象
        SomeService proxy=(SomeService) ctx.getBean("someService");
        //通过代理的对象执行方法,实现目标方法执行时,增强了功能

        String str=proxy.doOther("张三",23);
        System.out.println(str);
//
//        Student student = proxy.doOther2("张三",29);
//
//        System.out.println("信息:"+student);
    }
}

运行结果1:在这里插入图片描述
运行结果2:在这里插入图片描述

总结:使用@Afterreturning注解的执行顺序是:
先Object res=doOther();
然后myAfterReturning(res);
所以在切面类方法中即使更改返回值res的值,并不会影响doOther()方法的返回值,例如运行结果1
但是如果返回值是一个引用类型,更改了引用类型的属性,返回值会发生变化,例如运行结果2。具体什么原理还不明白(待处理)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值