您的位置:首页 > 编程语言 > ASP

Case:接口实现类的方法上使用AspectJ方式实现aop的异常问题

2017-07-30 10:29 716 查看

Case:接口实现类的方法上使用AspectJ方式实现aop的异常问题

现象:

在接口实现类的方法上定义AOP注解,但是在AOP注解执行方法内部无法获取注解类的实例

问题简化如下:

接口:

package reflect;
interface TestInterface{
void print();
}


接口实现类:

package reflect;
class Test implements TestInterface{
public void print() {
System.out.println("I am print");
}
}


注解类:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Log{
String value() default "";
}


AOP执行方法:

@Around("@annotation(reflect.Log)")
public Object process(ProceedingJoinPoint joinPoint) {
//根据切入点获取类名、方法名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
String methodName = method.getName();
String className = method.getDeclaringClass().getSimpleName();

//获取注解中的参数
Log log = method.getDeclaredAnnotation(Log.class);
String value = log.value();

// 参数操作
......

Object object = null;
try {
object = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return object;
}


在执行到process方法中时,获取到的methodName值是print,className值是TestInterface,method.toString结果是:public abstract void reflect.TestInterface.print(),log值是null。

疑问:预想情况下,log值不应该是null,而是Log注解类的实例;className值应为Test,method执行toString方法的结果应为:public void reflect.Test.print()

分析:

在process方法中断点,观察线程执行堆栈如下:



从上图看到,process方法是被$Proxy75代理类间接调用的,说明AOP底层实现是JDK动态代理。

在JDK动态代理中,程序通过生成实现被代理类接口的代理类达到代理的目的。在生成的代理类中,被代理类方法对应的Method实例是通过被代理类实现的接口获取的。这个Method实例通过方法调用层层传递,在process方法中,被封装到MethodInvvocationProceedingJoinPoint对象的joinPoint实例中。所以在process方法中获取对应参数时才会出现之前奇怪的结果。

jdk动态代理执行流程详见:JDK动态代理执行流程解析

通过以上分析可知,传入process方法的Method实例是TestInterface接口中print方法的Method实例,不是Test实现类的print方法的Method实例,所以在process方法中无法通过调用method.getDeclaredAnnotation方法获取Log注解实例。

解决:

将applicationContext.xml中的

<aop:aspectj-autoproxy />


改成

<aop:aspectj-autoproxy proxy-target-class="true" />


问题解决。

其实质是,在AOP动态代理的实现方式上,使用cglib代理代替jdk动态代理。

(TODO:关于cglib动态代理的实现原理以后再写)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  aop java动态代理
相关文章推荐