在主执行块之前和之后将代码注入到方法中
Injecting code into methods before and after main execution block
我有几个 类 实现了一个特定的 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);
}
问题是我需要将其复制粘贴到 sayIt()
方法的每个实现中,用于实现 Talk
接口的每个 class
,而我不需要真的很想这样做,因为...
- 它造成了很多重复。
- 随着更多的实现,您开始为维护而头疼,尤其是当您决定稍微更改实现时。
- 我很懒,喜欢写尽可能少的代码,同时尽可能多地重用。
那么问题来了....如何实现一次编写,多次使用的目标?方法计时是一个应用,但我真的只是希望能够"inject"代码在方法的开头和结尾。
我真的在寻找一个 工作示例 (不仅仅是 link 到更多 link )可能有用的东西(我'我猜是 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
调用包装在抽象 class 通用方法中?
abstract class AbstractTalk implements Talk {
public void sayIt() {
trace();
startMeasure();
doSayIt();
stopMeasure();
}
abstract protected doSayIt(); // here implement the logic
}
我有几个 类 实现了一个特定的 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);
}
问题是我需要将其复制粘贴到 sayIt()
方法的每个实现中,用于实现 Talk
接口的每个 class
,而我不需要真的很想这样做,因为...
- 它造成了很多重复。
- 随着更多的实现,您开始为维护而头疼,尤其是当您决定稍微更改实现时。
- 我很懒,喜欢写尽可能少的代码,同时尽可能多地重用。
那么问题来了....如何实现一次编写,多次使用的目标?方法计时是一个应用,但我真的只是希望能够"inject"代码在方法的开头和结尾。
我真的在寻找一个 工作示例 (不仅仅是 link 到更多 link )可能有用的东西(我'我猜是 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
调用包装在抽象 class 通用方法中?
abstract class AbstractTalk implements Talk {
public void sayIt() {
trace();
startMeasure();
doSayIt();
stopMeasure();
}
abstract protected doSayIt(); // here implement the logic
}