spring4 使用logback不打印日志

背景

工程中使用的spring4.2.6,在web.xml配置了logback的listener加载logback配置文件,使用logback打印日志,但是启动后spring core模块使用jcl(jarakta commons logging)打印,后边的使用logback打印。

分析

通过maven dependency发现,工程引入了jcl(jarakta commons logging)、log4j、slf4j、logback等日志包。查阅spring官方文档 得知,spring core模块使用的jcl日志,这也就解释了,为什么前半部分用jcl打印,所以,需要将其他日志实现引入到slf4j。为了达到这个目的,需要做以下措施

修正

  • 将commons-logging包全部移除,并引入jcl-over-slf4j.jar,这个包有两个作用,第一,防止出现jcl类的classnotfoundexception;第二,并将此类log引入slf4j。
  • 将log4j包全部移除,并引入log4j-over-slf4j.jar,作用同上,防止使用log4j的程序出现clasnotfoundexception,并将此类log引入slf4j
  • 将web.xml中logbacklistener放在所有listener的前面,首先执行logbackconfiglistener然后再执行spring的listener防止,这一点牵扯到了listener—–>filter—–>servlet的初始化顺序

所以最终的配置就是

jcl-over-slf4j.jar
logback-classic.jar
logback-core.jar

做完以上后,log恢复正常了。

收获

这个问题,解答了我之前的很多疑惑:系统中存在多个日志实现,比如jcl、log4j,第一,怎么将所有日志统一到某一个实现?第二,如果移除这些jar包,又会出现ClassNotFoundException,又该怎么解决?答案很简单,桥接!拿jcl举例,引入的jcl-over-slf4j.jar,就是将日志引入到slf4j,里边含有jcl的类,所以不会出现ClassNotFoundException,打开jcl-over-slf4j.jar与commons-logging.jar,你会发现类都一样。
这里写图片描述

桥接模式在jcl的实现

桥接模式很简单,就是A类引用了另一个类B,A类的方法最终都走的B类的方法。
这里jcl-over-slf4j,实现原理是桥接模式,看jcl-over-slf4j.jar的类LoggerFactory中包含了slf4j的LoggerFactory,这是第一个桥接模式的应用;

 public static LogFactory getFactory() throws LogConfigurationException {
        return logFactory;
    }
 static LogFactory logFactory = new SLF4JLogFactory();

返回的jcl logger类中,引用了slf4j的logger,这是第二个桥接模式的应用;

 public Log getInstance(String name) throws LogConfigurationException {
        Log instance = loggerMap.get(name);
        if (instance != null) {
            return instance;
        } else {
            Log newInstance;
            Logger slf4jLogger = LoggerFactory.getLogger(name);
            if (slf4jLogger instanceof LocationAwareLogger) {
                newInstance = new SLF4JLocationAwareLog((LocationAwareLogger) slf4jLogger);
            } else {
                newInstance = new SLF4JLog(slf4jLogger);
            }
            Log oldInstance = loggerMap.putIfAbsent(name, newInstance);
            return oldInstance == null ? newInstance : oldInstance;
        }
    }

这里看SLF4J的实现,日志最终都走的logger,而logger就是上边传入的slf4jLogger,slf4jLogger来自SLF4JFactory

public class SLF4JLog implements Log, Serializable {

    private static final long serialVersionUID = 680728617011167209L;

    // used to store this logger's name to recreate it after serialization
    protected String name;

    // in both Log4jLogger and Jdk14Logger classes in the original JCL, the
    // logger instance is transient
    private transient Logger logger;

    SLF4JLog(Logger logger) {
        this.logger = logger;
        this.name = logger.getName();
    }
}

正是这两个桥接模式的应用才使的jcl的log引入到slf4j中

我们再联想,slf4j-xx.jar(),很多这种jar,也是这个道理,桥接模式的应用;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值