1.创建接口类和它的实现类
package com.bjpowernode.ba02;
public interface SomeService {
void doSome(String name,Integer age);
String doOther(String name,Integer age);
}
package com.bjpowernode.ba02;
//目标类
public class SomeServiceImpl implements SomeService {
@Override
public void doSome(String name,Integer age) {
//给doSome方法增加一个功能,在doSome()执行之前,输出方法执行的时间
System.out.println("====目标方法doSome()执行====");
}
@Override
public String doOther(String name, Integer age) {
System.out.println("====目标方法doOther()执行====");
return "abcd";
}
}
2.创建切面类
package com.bjpowernode.ba02;
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();
* 参数传递: 传值, 传引用
* myAfterReturing(res);
* System.out.println("res="+res)
*
*/
@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "res")
public void myAfterReturning(Object res){
//Object res是目标方法执行后的返回值,根据返回值做切面功能的处理
System.out.println("后置通知:在目标方法之后执行的,获取的返回值是" + res);
}
}
3.在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: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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--把对象交给spring容器,由spring容器统一创建,管理对象-->
<!--声明目标对象-->
<bean id="someService" class="com.bjpowernode.ba02.SomeServiceImpl" />
<!--声明切面类对象-->
<bean id="myAspect" class="com.bjpowernode.ba02.MyAspect" />
<!--声明自动代理生成器:使用aspectj框架内部的功能,创建目标对象的代理对象。
创建代理对象是在内存中实现的, 修改目标对象的内存中的结构。 创建为代理对象
所以目标对象就是被修改后的代理对象.
aspectj-autoproxy:会把spring容器中的所有的目标对象,一次性都生成代理对象。
-->
<aop:aspectj-autoproxy/>
</beans>
4.编写测试类进行测试
package com.bjpowernode;
import com.bjpowernode.ba02.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest02 {
@Test
public void test02(){
String config="applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
//从容器中获取目标对象
SomeService proxy = (SomeService) ctx.getBean("someService");
//com.sun.proxy.$Proxy8:jdk动态代理
System.out.println("proxy:"+proxy.getClass().getName());
//通过代理的对象执行方法,实现目标方法执行时,增强了功能
proxy.doOther("zzh",30);
}
}
5.修改res,并不会改变目标方法的返回值,因为这里的参数传递是值传递