Log4j1迁移至Log4j2:如何创建自定义Logger并适配原有继承Logger的代码
解决Log4j 1转Log4j 2自定义Logger的适配问题
我完全懂你现在的困境——Log4j 1到2的变更确实有点“伤筋动骨”,原来继承org.apache.log4j.Logger的路子直接走不通了,全量实现Log4j2的Logger接口又太繁琐,继承LogManager也不是你想要的。其实最适合你的方案是用装饰器模式包装Log4j2的Logger实例,既不用写大量冗余代码,又能保留你自定义Logger的逻辑。
核心思路:组合而非继承
放弃继承Log4j的类/接口,转而在自定义的MyLogger内部持有一个Log4j2标准的Logger实例,所有日志操作都委托给这个实例来完成。这样既规避了实现全量接口的麻烦,又能完全适配Log4j2的特性。
修改后的完整代码示例
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import java.util.concurrent.ConcurrentHashMap; import java.util.Map; /** * 自定义Logger,适配Log4j2 */ public final class MyLogger { // 内部持有Log4j2的Logger实例 private final Logger loggerInstance; // 用ConcurrentHashMap缓存每个类对应的MyLogger实例(优化原单例逻辑) private static final Map<Class<?>, MyLogger> LOGGER_CACHE = new ConcurrentHashMap<>(); // 私有构造,直接传入Log4j2的Logger实例 private MyLogger(Logger loggerInstance) { this.loggerInstance = loggerInstance; } /** * 获取对应类的自定义Logger实例 * @param clazz 目标类 * @return 自定义Logger */ public static MyLogger getLogger(Class<?> clazz) { // 保证每个类仅创建一个MyLogger实例,线程安全 return LOGGER_CACHE.computeIfAbsent(clazz, key -> new MyLogger(LogManager.getLogger(key))); } // 你的自定义warn方法,直接委托给内部Logger实例 public void warn(Object message) { loggerInstance.warn(message); } // 如果你需要重载warn方法(比如带异常的版本),同样委托即可 public void warn(Object message, Throwable throwable) { loggerInstance.warn(message, throwable); } // 其他你需要的日志方法,比如info、error,以此类推 public void info(Object message) { loggerInstance.info(message); } public void error(Object message, Throwable throwable) { loggerInstance.error(message, throwable); } // 如果你需要暴露内部的Log4j2 Logger实例,保留getter即可 public Logger getLoggerInstance() { return loggerInstance; } }
关键修改点说明
- 依赖替换:把原来的
org.apache.log4j.Logger替换成Log4j2的org.apache.logging.log4j.Logger和org.apache.logging.log4j.LogManager。 - 去掉继承关系:不再继承任何Log4j的类/接口,改为内部持有Log4j2的
Logger实例。 - 优化单例逻辑:用
ConcurrentHashMap缓存每个类对应的MyLogger实例,避免原代码中每次调用getLogger都创建新实例的问题,同时保证线程安全。 - 方法委托:所有自定义的日志方法(比如
warn)都直接调用内部loggerInstance的对应方法,完全复用Log4j2的原生能力。
适配原有业务代码
原来业务代码里的调用方式不需要做任何修改,比如:
public class TestService { private static final MyLogger logger = MyLogger.getLogger(TestService.class); public void doSomething() { logger.warn("这是一条警告日志"); logger.info("这是一条信息日志"); } }
完全可以直接复用,不需要调整。
内容的提问来源于stack exchange,提问作者NoobCoder
相关产品推荐
相关产品推荐

