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

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



    增强织入的顺序
    一个连接点可以同时匹配多个切点,切点对应的增强在连接点上的织入顺序到底是如何安排呢?这个问题需要分三种情况讨论:
 如果增强在同一个切面类中声明,则依照增强在切面类中定义的顺序进行织入;
 如果增强位于不同的切面类中,且这些切面类都实现了org.springframework.core.Ordered接口,则由接口方法的顺序号决定(顺序号小的先织入);
 如果增强位于不同的切面类中,且这些切面类没有实现org.springframework.core.Ordered接口,织入的顺序是不确定的。
我们可以通过下图描述这种织入的规则:


图 9 增强织入顺序

    切面类A和B都实现为Ordered接口,A切面类对应序号为1,B切面类对应序号为2,A切面类按顺序定义了3个增强,B切面类按顺序定义两个增强,这5个增强对应的切点都匹配某个目标类的连接点,则增强织入的顺序为图中虚线所示。
访问连接点信息

    AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:
1)JoinPoint
 java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
 Signature getSignature() :获取连接点的方法签名对象;
 java.lang.Object getTarget() :获取连接点所在的目标对象;
 java.lang.Object getThis() :获取代理对象本身;
2)ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
 java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
 java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
    让我们来看一个具体的实例:
    代码清单 9 TestAspect:访问连接点对象

package com.baobaotao.aspectj.advanced; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class TestAspect { @Around("execution(* greetTo(..)) && target(com.baobaotao.NaiveWaiter)") ①环绕增强 public void joinPointAccess(ProceedingJoinPoint pjp) throws Throwable{ ②声明连接点入参 System.out.println("------joinPointAccess-------"); ③ 以下两行访问连接点信息 System.out.println("args[0]:"+pjp.getArgs()[0]); System.out.println("signature:"+pjp.getTarget().getClass()); pjp.proceed(); ④ 通过连接点执行目标对象方法 System.out.println("-------joinPointAccess-------"); } }

    在①处,我们声明了一个环绕增强,在②处增强方法的第一个入参声明为PreceedingJoinPoint类型(注意一定要在第一个位置),在③处,我们通过连接点对象pjp访问连接点的信息。在④处,我们通过连接点调用目标对象的方法。
执行以下的测试代码:

String configPath = "com/baobaotao/aspectj/advanced/beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter naiveWaiter = (Waiter) ctx.getBean("naiveWaiter"); naiveWaiter.greetTo("John");

    输出以下的信息:
    ------joinPointAccess-------
    args[0]:John
    signature:class com.baobaotao.NaiveWaiter
    NaiveWaiter:greet to John... ①对应pjp.proceed();
    -------joinPointAccess-------

1 2 3 4 5 6
【内容导航】
第1页: 切点复合运算 第2页: 命名切点
第3页: 第3页 第4页: 第4页
第5页: 第5页 第6页: 第6页
©版权所有。未经许可,不得转载。
[责任编辑:赵恒]