如何使用AspectJ访问私有字段?

时间:2017-08-16 13:02:23

标签: java aop aspectj

我正在调查AspectJ及其众多用途,并发现了mixins

我可以找到许多使用纯AspectJ .aj方面的示例,但我只需要使用@AspectJ注释。

我想要实现的目标如下: -

我有一个我无法修改的类,它有一个私有类变量,我需要在特定的类方法完成执行后进行查询。此类没有与此私有类变量关联的getter或setter方法。

public final class CannotAmend {

    private Uri privateUri;

    public final void methodOne(){}

    public final void methodTwo(){}

    public final void methodThree(){

        privateUri = "something";   

    }
}

我需要一个可以捕获@After methodThree()的方面/混合,并允许我查看privateUri中设置的值。

这可能实现吗?

使用@AspectJ注释?

我在哪里可以找到如何实现这一目标的文档/教程/示例?

2 个答案:

答案 0 :(得分:3)

在某个方面,您可以使用反射API访问私有字段。

在这方面你需要两件事:

  • 用于定义方面匹配的方法的切入点。
  • 使用@After注释的方法包含在切入点匹配的方法返回后执行的逻辑。
@Aspect
public class MyAspect {

    @Pointcut("execution(* CannotAmend.methodThree(..))")
    public void methodThreePointcut(){
    }

    @After("methodThreePointcut()")
    public void afterMethod(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {
        Object instance = joinPoint.getThis();

        Field privateUriField = instance.getClass().getDeclaredField("privateUri");
        privateUriField.setAccessible(true);

        String privateUri = (String) privateUriField.get(instance);
        System.out.println(privateUri); // prints "something"
    }
}

另外,使用String常量来访问私有字段并不是一个干净的解决方案。如果将来某个时候变量的名称发生变化,或者如果它被删除,则该方面将会中断。

答案 1 :(得分:1)

不是使用mixins,但您可以使用@Around建议获取JoinPoint并通过反射获取字段。 例如:

@Around("execution(* *.methodThree())")
public Object getValue(ProceedingJoinPoint pjp) throws Throwable {
    try {
        return pjp.proceed();
    } finally {
        System.out.println(pjp.getThis().getClass().getDeclaredField("privateUri").get(pjp.getThis()));
    }
}