转载自,原文格式更清晰:https://blog.csdn.net/cleverutd/article/details/8607491
最近boss叫我用spring aop做一个试验,说是之后一个新项目要用到,大体需求如下:拦截某个函数的返回值,并修改之。
因为之前我对AOP的认识只是停留在上课时老师跟我们传授的理论阶段,从未写过代码实践过,因此这次我花了一定的时间去做了这个试验。一开始打算上网直接查找相关代码,但是发觉都没有达到我预期的效果,于是决定自己写一个。一开始我打算用后置增强来解决,但是发现只能获取返回值,并不能改变它,之后在stackOverflow问了一下,经过一个网友的提示,终于fix掉了,核心是用环绕增强和ProceedingJoinPoint,废话少说,直接贴代码
定义目标业务类
-
public
class AopDemo implements IAopDemo{
-
-
public String doSth(String task){
-
System.out.println(
"do somthing.........."+task);
-
return task;
-
}
定义切面,参数ProceedingJoinPoint 通过直接打印pjp,会看到控制台输出一句execution(String com.toby.aop.IAopDemo.doSth(String)),说明pjp是当前被调用的切点方法的引用
-
public
class Listener {
-
-
public Object around(ProceedingJoinPoint pjp) throws Throwable{
-
System.out.println(
"beginning----");
-
Object object = pjp.proceed();
//运行doSth(),返回值用一个Object类型来接收
-
object =
"Mission Two";
//改变返回值
-
System.out.println(
"ending----");
-
return object;
-
}
-
}
配置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:util=
"http://www.springframework.org/schema/util"
-
xmlns:context=
"http://www.springframework.org/schema/context"
-
xmlns:tx=
"http://www.springframework.org/schema/tx"
-
xmlns:aop=
"http://www.springframework.org/schema/aop"
-
-
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-
http://www.springframework.org/schema/tx
-
http://www.springframework.org/schema/tx/spring-tx.xsd
-
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
-
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
-
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
-
-
<bean id="aopDemo" class="com.toby.aop.AopDemo"/>
-
<bean id="listener" class="com.toby.aop.Listener"/>
-
<aop:config>
-
<aop:aspect id="myListener" ref="listener">
-
<aop:pointcut expression="execution(* com.toby.aop.AopDemo.*(..))" id="listenerCut"/>
-
-
<aop:around method="around" pointcut-ref="listenerCut"/>
-
</aop:aspect>
-
</aop:config>
-
</beans>
测试
-
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(
"spring-context-common.xml");
-
IAopDemo demo = (IAopDemo)context.getBean(
"aopDemo");
-
System.out.println(demo.doSth(
"Mission One"));
程序运行结果
beginning----
do somthing..........Mission One
ending----
Mission Two
调用doSth()后,@Around定义的around()方法里通过拦截返回值"Mission One",并修改为“Mission Two”返回,也就是说,doSth的返回值最后其实是around()的返回值