1. 背景
最近在写新的基于SPI日志框架时,起初当判断当前没有Appender实例时,我会抛出异常来阻断系统。阳哥Review后建议“捕获日志框架的所有异常,不要影响应用的正常逻辑”。
2. 解决方案
- 参考Slf4j的实现,没有找到Appender实例时,只打印error日志。
- SessionLogger设置动态代理,来catch其所有的方法,避免异常上浮。
private static final ThreadLocal<ISessionLogger> loggerThreadLocal = new ThreadLocal() {
private final IAppender appender = AppenderFactory.getAsyncAppender();
@Override
protected ISessionLogger initialValue() {
ISessionLogger sessionLogger = new SessionLoggerImpl();
sessionLogger.setAppender(appender);
return (ISessionLogger) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[]{ISessionLogger.class},
(proxy, method, args) -> {
try {
Object ret = method.invoke(sessionLogger, args);
return ret;
} catch (Throwable throwable) {
return null;
}
});
}
};
3. 反思
一个系统的异常处理逻辑要分模块的去考虑,考虑该模块在系统的所处的位置。
- 日志框架是系统的辅助模块。它的异常不能上浮到应用逻辑里,即不能因为日志记录异常而影响整个系统的业务处理。
- 不久前开发的Maven插件用来编译生成线上的运行包。如果执行异常,则其生成的代码大概率是错误的。此时一定要抛出异常来中断Maven打包过程,避免运行错误的代码。