AspectJ: как получить значение поля доступа в GET () pointcut


Я пишу регистратор аспектов для записи журнала при каждом обращении к любой переменной-члену в данном классе.

Если я напишу определенный точечный разрез для одной переменной, как показано ниже, я смогу получить значение поля.

@Pointcut("get(* abc.ThreadPoolService.drMaxTh)")
public void drFields() {}

@AfterReturning(pointcut="drFields()", returning="drMaxTh")  
public void afterAccessingdrFields(int drMaxTh) {
    LOGGER.info("Accessed the field drMaxTh " + drMaxTh);
}

Но у моего класса есть дюжина переменных+, и я не собираюсь писать конкретные точечные разрезы для каждого из них. Итак, я хочу написать что-то вроде..

@Pointcut("get(* abc.ThreadPoolService.*)")
public void drFields() {}

@AfterReturning(pointcut="drFields()", returning= **????** )  
public void afterAccessingdrFields(what should come here???) {
    LOGGER.info("Accessed the field drMaxTh " + <and here???>);
}

Но не в состоянии понять, как захватить имя и значение поля, которое используется доступ, в случае спецификатора доступа к полю с подстановочными знаками.

Спасибо всем, кто помогает мне в этом.

1 3

1 ответ:

На самом деле это очень просто, и sheltem был прав, вы можете просто использовать Object в объявлении возвращаемого типа. Вот небольшая демонстрация, показывающая, что он даже работает как для статических, так и для нестатических членов, пока они не объявлены final:

Применение драйвера:

package de.scrum_master.app;

public class Application {
    public static final double PI = Math.PI;
    static String producer = "Scrum-Master.de";

    private int id = 11;
    private String author = "Alexander Kriegisch";
    private final String COUNTRY = "Germany";

    public static void main(String[] args) {
        Object dummy;
        Application application = new Application();

        // Access static fields
        dummy = PI;
        dummy = producer;
        // Access non-static fields
        dummy = application.author;
        dummy = application.id;
        dummy = application.COUNTRY;
    }
}

Аспект:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class FieldAccessLogger {
    @Pointcut("get(* de.scrum_master.app.Application.*)")
    public void fieldAccess() {}

    @AfterReturning(pointcut = "fieldAccess()", returning = "field")
    public void afterFieldAccess(Object field, JoinPoint thisJoinPoint) {
        System.out.println(thisJoinPoint.toLongString());
        System.out.println("  " + thisJoinPoint.getSignature().getName());
        System.out.println("  " + field);
    }
}

Вывод на консоль:

get(static java.lang.String de.scrum_master.app.Application.producer)
  producer
  Scrum-Master.de
get(private java.lang.String de.scrum_master.app.Application.author)
  author
  Alexander Kriegisch
get(private int de.scrum_master.app.Application.id)
  id
  11
Как вы можете видеть, PI и COUNTRY не перехватываются, потому что они являются (конечными) константами.