Nutz 的日志模块提供统一调用接口,再适配具体输出实现。阅读这层代码,重点是业务代码怎样取得 logger,以及运行时怎样选择可用适配器。以下固定使用 1.b.53,适配器列表与优先级不能跨版本直接推断。
三层职责
| 类型 | 职责 |
|---|---|
| Logs | 静态工厂与适配器选择 |
| Log | 日志级别判断及输出方法 |
| LogAdapter | 根据名称返回 Log,接口方法为 getLogger |
import org.nutz.log.Log;
import org.nutz.log.Logs;
public class ExampleService {
private static final Log log = Logs.getLog(ExampleService.class);
public void run() {
log.info("task started");
}
}
显式传入类名比较直观。Logs.get() 还会通过当前调用栈推导名称,不能将它和不存在的 Logs.get(Class) 重载混写。
默认选择有明确版本范围
1.b.53 的 Logs.init 通过 SimplePluginManager 依次尝试 Log4jLogAdapter 和 SystemLogAdapter。可用性检测决定实际使用哪个,而不是看到 classpath 里有某个日志 jar 就认定一定生效。后续版本可能支持其他适配器,应查看对应实现。
Logs.setAdapter 可以显式设置适配器,但已有代码保存的 Log 引用未必会随之后续切换;应在初始化时统一决定。NOP_ADAPTER 提供无输出实现,是空对象策略,不是一个“没有实现完”的异常分支。
日志外观仍有维护成本
业务依赖统一接口,有利于隔离具体实现,但桥接和适配器也可能形成重复输出或循环。排查时确认实际绑定、配置加载及调用路径,避免同时添加多套桥接来碰运气。
日志级别、异常堆栈和上下文决定定位问题的价值。大量日志也会消耗 IO,输出内容还可能包含敏感数据,所以需要与业务观测目标一起设计,而不是只确认能打印一行文字。