关于编程创建Logback DBAppender的关闭与多Logger复用问询
Logback DBAppender 编程式创建相关问题解答
先贴出你提供的编程式创建DBAppender的代码:
Logger logger = LoggerFactory.getLogger(loggerName); DBAppender dbAppender = new DBAppender(); DataSourceConnectionSource connectionSource = new DataSourceConnectionSource(); ComboPooledDataSource cpds = new ComboPooledDataSource(); try { cpds.setDriverClass("oracle.jdbc.driver.OracleDriver"); cpds.setJdbcUrl(dbConfig.getJdbcUrl()); cpds.setUser(dbConfig.getUserID()); cpds.setPassword(dbConfig.getPassword()); } catch (PropertyVetoException e) { Logs.error("Unable to set driver class. PropertyVetoException: " + e); } connectionSource.setDataSource(cpds); connectionSource.setContext(logger.getLoggerContext()); connectionSource.start(); dbAppender.setConnectionSource(connectionSource); dbAppender.setContext(logger.getLoggerContext()); dbAppender.start(); logger.addAppender(dbAppender);
接下来针对你提出的两个问题逐一解答:
问题1:应用停止时是否需要手动关闭连接源,执行类似connectionSource.stop(); dbAppender.stop();的操作?
答案是非常建议手动执行这些停止操作,原因如下:
- 虽然Logback的
LoggerContext在Web应用的contextDestroyed阶段,或者部分框架管理的应用关闭流程中,会自动调用所有关联组件的stop()方法,但如果是非Web环境、或者存在上下文销毁逻辑未被触发的特殊场景,手动调用能彻底避免数据库连接池、Appender资源泄漏。 - 你代码里用的
ComboPooledDataSource是连接池实现,connectionSource.stop()会间接触发连接池关闭,释放所有持有的数据库连接;dbAppender.stop()会清理Appender内部的缓存、线程等资源,确保应用停止后不会有残留的日志写入逻辑运行。 - 手动执行能让你更精准地控制资源释放时机,避免因Logback上下文销毁延迟导致的连接池资源占用问题。
问题2:若存在多个Logger,是否可以为所有Logger共用一个DBAppender?所有Logger的上下文是否一致?
这两个问题的答案都是肯定的:
- 完全可以共用一个DBAppender:
多个Logger共用同一个DBAppender是非常推荐的最佳实践,这样能避免创建多个重复的Appender实例和连接池,节省数据库连接、内存等系统资源。你只需要创建一次DBAppender和对应的connectionSource,然后调用每个需要的Logger的addAppender()方法即可。 - 同一个应用内的Logger上下文默认是一致的:
除非你手动创建了多个LoggerContext实例,否则通过LoggerFactory.getLogger()获取的所有Logger,它们的getLoggerContext()返回的都是同一个全局上下文实例。所以你只需要从任意一个Logger获取上下文,设置给connectionSource和dbAppender就足够了,不需要为每个Logger重复设置。
内容的提问来源于stack exchange,提问作者Yaroslav Ivchenkov
相关产品推荐
相关产品推荐

