捕获方法对象作为建议 AspectJ 中的参数

Capture Method object as parameter in the advice AspectJ

我需要在执行一个方法之前执行一些检查,但我需要通过反射将这个方法作为一个对象获取,然后将其作为回调传递给另一个对象。例如:

我有一个视图控制器,我需要使用特定注释对某些方法进行访问控制。此方法导航到需要通过先前配置的密码进行控制访问的视图。

    @AccessControl(accessID = "bookKeysViewId")
    private void navigateToBookKeys() {
        navigateTo(ControllerPasswordBookKey.class);
    }

在执行该方法之前,我需要检查访问权限。例如:

pointcut makeAccessControl() : execution(@AccessControl * *(..));

before() : makeAccessControl(){
    Method method =  // any way to get the intercepted method
    String idAccess = // get de access id from method annotation
    EnumTypeAccess typeAccess = ManagerAccess.checkAccess(idAccess);
    switch (typeAccess ){
            case NEEDED: openPasswordDialog();break; // wrong password ?  throw an exception and interrupt the method execution.
            case NEED_CONFIG: // create configuration view, pass "method" as callback and navigate to it
        }


}

让我们来看看这个小MCVE:

标记注释:

package de.scrum_master.app;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface AccessControl {
  String accessID();
}

驱动申请:

package de.scrum_master.app;

public class Application {
  public void doSomething() {
    navigateToBookKeys();
  }

  @AccessControl(accessID = "bookKeysViewId")
  private void navigateToBookKeys() {}

  public static void main(String[] args) {
    new Application().doSomething();
  }
}

看点:

您可以通过 @annotation(accessControl) 将您的方法注释绑定到通知参数,并在切入点中声明该参数及其类型(或直接在内联切入点的通知中)。

你想要的 Method 对象(无论出于何种原因)你可以通过 ((MethodSignature) thisJoinPoint.getSignature()).getMethod().

获得
package de.scrum_master.aspect;

import java.lang.reflect.Method;
import org.aspectj.lang.reflect.MethodSignature;
import de.scrum_master.app.AccessControl;

public aspect AccessControlAspect {
  pointcut makeAccessControl(AccessControl accessControl) :
    @annotation(accessControl) &&
    execution(* *(..));

  before(AccessControl accessControl) : makeAccessControl(accessControl) {
    Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
    String accessID = accessControl.accessID();
    System.out.println(thisJoinPoint);
    System.out.println("  method   = " + method);
    System.out.println("  accessID = " + accessID);
  }

}

控制台日志:

execution(void de.scrum_master.app.Application.navigateToBookKeys())
  method   = private void de.scrum_master.app.Application.navigateToBookKeys()
  accessID = bookKeysViewId