我认为这是可能的。这是我发现的:
如果您使用的是 Java 8,您可以向编译器注册 Plugin 以在编译期间添加一些额外的功能。文档对插件有这样的说法:
预计一个典型的插件会简单地注册一个TaskListener,以便在编译执行期间被通知事件,其余的工作将由任务监听器完成。
因此,您可以设置一个插件来使用 TaskListener,并在生成类时让任务侦听器记录时间戳。
package xyz;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
public class TimestampPlugin implements Plugin {
@Override
public String getName() {
return "Timestamp_Plugin";
}
@Override
public void init(JavacTask task, String... strings) {
task.setTaskListener(new FileTimestampListener());
}
}
Documentation for TaskListener。任务监听器被传递一个TaskEvent,它有一个Kind。在您的情况下,听起来您对生成感兴趣。
package xyz;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import java.util.HashMap;
public class FileTimestampListener implements TaskListener {
HashMap<String, Long> timeStampMap = new HashMap<>();
@Override
public void started(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
timeStampMap.put(name, System.currentTimeMillis());
}
}
@Override
public void finished(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
System.out.println("Generated " + name + " over " + (System.currentTimeMillis() - timeStampMap.get(name)) + " milliseconds");
}
}
}
这是一个简单的示例,但从这里开始设置日志文件之类的东西来存储收集到的信息应该很简单。正如您在插件的 init 函数中看到的那样,可以从命令行将参数传递给插件。
通过使用 -Xplugin 编译器参数指定插件来配置插件。我不知道为什么,但似乎在this page 上没有任何关于它的文档,但可以通过设置一个名为 com.sun.source.util.Plugin 的文件(接口的 FQ 类名)来使用它实施)在您的 META-INF/services 目录中。所以:
META-INF
|-- services
|-- com.sun.source.util.Plugin
并在该文件中列出您实现该类的 FQ 类名称。所以文件内容是:
xyz.TimestampPlugin
在您的 Ant 任务中,您只需要指定编译器标志 -Xplugin:Timestamp_Plugin(注意这是插件的 getName() 函数提供的名称)。您还需要在类路径或注解处理器路径(如果已指定)上提供已编译的插件和运行时依赖项。