Java 在主执行块之前和之后将代码注入方法
我有两个类实现了一个特定的Java 在主执行块之前和之后将代码注入方法,java,performance,code-injection,Java,Performance,Code Injection,我有两个类实现了一个特定的接口,如下所示(这显然是一个非常简化的版本,但可以理解这一点): Talk的首次实现: import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SayHello implements Talk { static final Logger LOG = LoggerFactory.getLogger(SayHello.class); public SayHello() {}
接口
,如下所示(这显然是一个非常简化的版本,但可以理解这一点):
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");
}
}
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");
}
}
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");
}
}
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()
方法的每个实现都复制粘贴这个,我真的不想这样做,因为
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);
}
}
}
import org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入java.util.ArrayList;
导入java.util.List;
公共类其他类{
静态最终记录器日志=LoggerFactory.getLogger(SomeOtherClass.class);
公共SomeOtherClass(){}
公开会议{
List talks=new ArrayList();
添加(新的SayHello());
talks.add(new saybaye());
为了(谈话:谈话){
long startTime=System.currentTimeMillis();
trace(“为实现{}执行sayIT,开始时间为{}.”,talking.getClass().getSimpleName(),startTime);
说话;
LOG.trace(“sayIT for implementation{}花费了{}毫秒来执行。”,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
}
更广泛地说,是一个装饰师。@Kayaman,是的,你是100%正确的,这就是AspectJ试图做的。Spring也有一个AOP框架,但不幸的是,我没有在这个实现中使用Spring。如上所述,我正在寻找的是一个工作的例子。只是一个旁注。。。我已经修补了AspectJ,但是我一直很难让它正常工作。然而,我的问题有点宽泛的原因是我不希望它是一个具体的AspectJ实现问题,因为我对不同的建议感兴趣。很好的一点是,这个解决方案工作得相当好,而且它不具备代码注入的黑魔法。这将带来的唯一问题(至少在我的场景中)更多的是日志记录问题。日志输出将针对
AbstractTalk
,而不是SayHello
或saybye
。虽然我想人们总是可以使用类似于String callingThread=Thread.currentThread().getStackTrace()[2].getClassName()的东西
获取该信息。您可以始终为受保护的构造函数提供logger
参数,并在创建子类时提供适当的记录器实现yes,或者添加另一个返回logger