Доступ к закрытым статическим членам (например, регистраторам) из AspectJ - PullRequest
0 голосов
/ 31 января 2019

Предположим, у меня есть этот класс

public class MyClass {
    private Logger log = LogFactory.getLogger(MyClass.class);

    public void doSomething() {
        // doing something
    }
}

Предположим, что я хочу написать аспект для записи в журнал и выхода:

public aspect TraceAspect {

    pointcut method(): execution(* *(..));

    before(): method(){

        log.info("entering method");
    }

    after(): method(){
        log.info("existing method");
    }
}

Проблема в том, что я хочу получить доступобъект журнала внутри класса с аспектом, но я не знаю как.Я не хочу создавать новый регистратор, потому что я хочу сохранить все данные, связанные с регистратором классов, при ведении журнала.Есть ли способ или шаблон для доступа к данным класса?

EDIT: хотел заявить, что этот аспект должен отслеживать все классы, которые имеют поле журнала.То есть у меня может быть много классов: MyClass, MyClass1, YourClass2, RepositoryClass, и т. Д.

1 Ответ

0 голосов
/ 03 февраля 2019

То, что Нандор сказал, технически правильно, но мой совет: пожалуйста, избегайте доступа к закрытым членам или методам, когда это возможно, потому что они являются личными по какой-то причине.Например, они могут изменяться, даже если открытый интерфейс класса не изменяется.Таким образом, вы никогда не можете полагаться на их существование или их названия.Кроме того, сквозная задача должна также максимально соответствовать принципам проектирования, таким как инкапсуляция.

В данном конкретном случае речь идет о регистраторах Slf4J, точнее о вашем желании избежать создания избыточных объектов регистратора.Что ж, Slf4J не так глуп и небрежен, как вы можете подумать о создании объектов.Все классы, реализующие ILoggerFactory, используют внутреннюю карту для кэширования существующих регистраторов для заданных имен (классов), см., Например,

Так почему бы просто не расслабиться и не получить доступ к соответствующим регистраторам из своего аспекта, используя имена целевых классов.Это даже работает, если целевой класс не имеет собственного статического регистратора:

Классы приложений:

package de.scrum_master.app;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyClassWithLogger {
  private Logger log = LoggerFactory.getLogger(MyClassWithLogger.class);

  public void doSomething() {}
}
package de.scrum_master.app;

public class MyClassWithoutLogger {
  public void doSomething() {}
}
package de.scrum_master.app;

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

Аспект:

package de.scrum_master.aspect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public aspect TraceAspect {
  pointcut executedMethods(Object targetObject) :
    execution(!static * *(..)) && target(targetObject);

  before(Object targetObject) : executedMethods(targetObject) {
    Logger log = LoggerFactory.getLogger(targetObject.getClass());
    log.info("Entering " + thisJoinPoint);
  }

  after(Object targetObject) : executedMethods(targetObject) {
    Logger log = LoggerFactory.getLogger(targetObject.getClass());
    log.info("Exiting " + thisJoinPoint);
  }
}

Журнал консоли с Slf4J, настроенным для использования простого регистратора:

[main] INFO de.scrum_master.app.MyClassWithLogger - Entering execution(void de.scrum_master.app.MyClassWithLogger.doSomething())
[main] INFO de.scrum_master.app.MyClassWithLogger - Exiting execution(void de.scrum_master.app.MyClassWithLogger.doSomething())
[main] INFO de.scrum_master.app.MyClassWithoutLogger - Entering execution(void de.scrum_master.app.MyClassWithoutLogger.doSomething())
[main] INFO de.scrum_master.app.MyClassWithoutLogger - Exiting execution(void de.scrum_master.app.MyClassWithoutLogger.doSomething())
...