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

How do I access private fields with AspectJ?

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

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

我想要实现的是:-

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

public final class CannotAmend {

    private Uri privateUri;

    public final void methodOne(){}

    public final void methodTwo(){}

    public final void methodThree(){

        privateUri = "something";   

    }
}

我需要一个 aspect/mixin 可以捕获 @After methodThree() 并允许我看到 privateUri 中设置的值。

这可以实现吗?

@AspectJ个注释?

我在哪里可以找到 documentation/tutorial/examples 如何实现这一点?

不适用于 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()));
    }
}

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

在这方面你需要两件事:

  • 用于定义方面匹配的方法的切入点。
  • 并且用 @After 注释的方法包含在与切入点 returns 匹配的方法之后执行的逻辑。

@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"
    }
}

附带说明一下,使用字符串常量访问私有字段并不是一个干净的解决方案。如果将来某个时候变量的名称发生变化或者它被删除,方面将会中断。