从AspectJ访问私有静态成员(例如记录器)

时间:2019-01-31 15:43:24

标签: java aspectj

假设我有这个课程

$("#km-table-id.checkbox-class, [data-action='add']").on("click", faveFunc)

假设我要编写一个方面来记录日志的进入和退出:

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"); } } 等。

1 个答案:

答案 0 :(得分:1)

南多尔所说的在技术上是正确的,但我的建议是:请尽量避免访问私有成员或方法,因为它们出于某种原因是私有的。例如,即使类的公共接口没有更改,它们也可能会更改。因此,您永远不能依靠它们的存在或命名。此外,横切关注点也应符合设计原理等封装尽可能。

此特定情况与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())