商讯信箱
用户名: @
密  码:   注册|忘记密码
登录
个人用户经销商
您的位置:首页 > 技术频道 > 正文

基于@AspectJ配置Spring AOP(之二)

绑定连接点方法入参
我们介绍切点函数时说过args()、this()、target()、@args()、@within()、@target()和@annotation()这7个函数除了可以指定类名外,还可以指定参数名将目标对象连接点上的方法入参绑定到增强的方法中。
其中args()用于绑定连接点方法的入参,@annotation()用于绑定连接点方法的注解对象,而@args()用于绑定连接点方法入参的注解。来看一个args()绑定参数的实例:
代码清单 10 TestAspect:绑定连接点参数
package com.baobaotao.aspectj.advanced;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class TestAspect {
①绑定连接点参数,首先args(name,num,..)根据②处的增强方法入参找到name和num对应的
类型,以得到真实的切点表达式:target(com.baobaotao.NaiveWaiter) && args(String,int,..)
在该增强方法织入到目标连接点时,增强方法可以通过num和name访问到连接点方法的入参。
@Before("target(com.baobaotao.NaiveWaiter) && args(name,num,..)")
public void bindJoinPointParams(int num,String name){②增强方法接受连接点的参数
System.out.println("----bindJoinPointParams()----");
System.out.println("name:"+name);
System.out.println("num:"+num);
System.out.println("----bindJoinPointParams()----");
}
}
在①处,我们通过args(name,num,..)进行连接点参数的绑定,和前面我们所讲述的方式不一样,当args()函数入参为参数名时,共包括两方面的信息:
1) 连接点匹配规则信息:连接点方法第一个入参是String类型,第二个入参是int类型;
2) 连接点方法入参和增强方法入参的绑定信息:连接点方法的第一个入参绑定到增强方法的name参数上,第二个入参绑定到增强方法的num入参上。
切点匹配和参数绑定的过程是这样的:首先args()根据参数名称在增强方法中查到名称相同的入参并获知对应的类型,这样就知道匹配连接点方法的入参类型。其次连接点方法入参类型所在的位置则由参数名在args()函数中声明的位置决定。代码清单 10中的args(name,num)只匹配第一个入参是String第二个入参是int的目标类方法,如smile(String name,int times)而不匹配smile(int times ,String anme)。我们可以通过以下示意图详细了解这一有趣的匹配过程:

图 11 绑定参数和切点匹配过程
和args()一样,其它可以绑定连接点参数的切点函数(如@args()和target()等),当指定参数名时,就同时具有匹配切点和绑定参数的双重功能。
运行下面的测试:
String configPath = "com/baobaotao/aspectj/advanced/beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
NaiveWaiter naiveWaiter = (NaiveWaiter) ctx.getBean("naiveWaiter");
naiveWaiter.smile("John",2);
我们将看到以下的输出信息:
----bindJoinPointParams()----
name:John
num:2
----bindJoinPointParams()----
NaiveWaiter:smile to John2times...
可见,增强方法按预期绑定了NaiveWaiter.smile(String name,int times)方法的运行期入参。
提示 为了保证实例能成功执行,必须启用CGLib动态代理:<aop:aspectj-autoproxy proxy-target-class="true" />,因为该实例需要对NaiveWaiter类进行代理(因为NaiveWaiter#simle()方法不是Waiter接口的方法),所以必须使用CGLib生成子类的代理方法。
我们知道方法的入参名无法通过反射机制获取,所以Spring按以下方式
1 2 3 4 5 6
【内容导航】
第1页: 切点复合运算 第2页: 命名切点
第3页: 第3页 第4页: 第4页
第5页: 第5页 第6页: 第6页
©版权所有。未经许可,不得转载。
[责任编辑:赵恒]