@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。具体什么原理还不明白(待处理)