在主执行块之前和之后向方法中注入代码



我有几个类实现了一个特定的interface,如下所示(这显然是一个非常简化的版本,但能说明问题(:

public interface Talk {
void sayIt();
}

Talk:的首次实现

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SayHello implements Talk {
static final Logger LOG = LoggerFactory.getLogger(SayHello.class);
public SayHello() {}
public void sayIt() {
System.out.println("Hello");
}
}

Talk:的二次实现

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SayGoodbye implements Talk {
static final Logger LOG = LoggerFactory.getLogger(SayHello.class);
public SayGoodbye() {}
public void sayIt() {
System.out.println("GoodBye");
}
}

现在,在sayIt()方法中,我想实现一些跟踪级别的日志记录和一些方法执行计时器,我可以简单地做如下操作:

public void sayIt() {
long startTime = System.currentTimeMillis();
LOG.trace("Executing sayIT for implementation {} , start time at {}.", this.getClass().getSimpleName(), startTime);
System.out.println("Hello");
LOG.trace("sayIT for implementation {} took {} milliseconds to execute.", this.getClass().getSimpleName(), System.currentTimeMillis() - startTime);
}

问题是,对于实现Talk接口的每个class,我需要将其复制并粘贴到sayIt()方法的每个实现中,而我并不真的想这样做,因为。。。

  1. 它造成了大量的重复
  2. 随着实现的增多,您开始有一个维护难题,尤其是当您决定稍微更改实现时
  3. 我很懒,喜欢写尽可能少的代码,同时尽可能多地重用

所以问题来了。。。。我该如何实现一次写作,多次使用的目标?方法计时是一个应用程序,但我真的只想能够在方法的开头和结尾"注入"代码。

我真的在寻找一个的工作示例(不仅仅是指向更多链接的链接(,它可能会起作用(我猜是像AspectJ这样的东西,但我一直在为让它与Gradle一起工作而烦恼……可能只是尝试了一个Maven实现(

哦,是的,我可以不把代码添加到sayIt(),而是把它添加到调用sayIt()的代码中,例如:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class SomeOtherClass {
static final Logger LOG = LoggerFactory.getLogger(SomeOtherClass.class);
public SomeOtherClass() {}
public void letsHaveAConversation() {
List<Talk> talks = new ArrayList<>();
talks.add(new SayHello());
talks.add(new SayGoodbye());
for (Talk talking : talks) { 
long startTime = System.currentTimeMillis();
LOG.trace("Executing sayIT for implementation {} , start time at {}.", talking.getClass().getSimpleName(), startTime);
talking.sayIt();
LOG.trace("sayIT for implementation {} took {} milliseconds to execute.", talking.getClass().getSimpleName(), System.currentTimeMillis() - startTime);
}
}
}

这将起作用,但如果我有多个调用sayIt()的位置,则不会起作用。

为什么不将sayIt调用封装在抽象类公共方法中?

abstract class AbstractTalk implements Talk {
public void sayIt() {
trace();
startMeasure();
doSayIt();
stopMeasure();
}
abstract protected doSayIt(); // here implement the logic
}

最新更新