slf4j、log4j-slf4j-impl、log4j2之间的关系(更新ing)

日志框架:slf4j
日志实现:log4j2
桥接包:log4j-slf4j-impl

桥接包log4j-slf4j-impl起到适配的作用,因为市面上的日志实现互不兼容,日志框架slf4j要想适用于日志实现log4j2,就需要使用桥接包

slf4j使用LoggerFactory创建Logger进行日志打印,底层实际上调用了log4j-slf4j-impl的StaticLoggerBinder类创建一个Log4jLoggerFactory,然后再由这个Log4jLoggerFactory创建一个Log4j2的Logger对象,这个Logger封装在log4j-slf4j-impl中的Log4jLogger里面,最后将Log4jLogger返回给slf4j,每次slf4j进行日志打印,实际上是log4j-slf4j-impl中的Log4jLogger调用log4j2进行日志打印
如果没有 log4j-slf4j-impl桥接包,slf4j将创建一个对象,里面都是空方法,所以不会打印出日志

具体流程

		<!-- 日志实现 -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.1</version>
		</dependency>
		<!-- 日志桥接包   桥接包的版本须对应log4j2的版本 -->
  		<dependency>
		    <groupId>org.apache.logging.log4j</groupId>
		    <artifactId>log4j-slf4j-impl</artifactId>
		    <version>2.1</version>
		</dependency>
		<!-- 日志框架(门面) -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-api</artifactId>
		    <version>1.7.7</version>
		</dependency>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Test  {
	//slf4j获取logger进行日志打印
	private static final Logger logger= LoggerFactory.getLogger(Test.class);

	public static void main(String[] args) {
		logger.info("slf4j 打印日志");
	}
}

//LoggerFactory(slf4j)
public static Logger getLogger(String name) {
/*
ILoggerFactory 是一个接口,实际上getILoggerFactory返回的是Log4jLoggerFactory(桥接包提供,ILoggerFactory 的实现类)
*/
    ILoggerFactory iLoggerFactory = getILoggerFactory();
/*
Log4jLoggerFactory(桥接包)创建Logger ,实际上调用了它的父抽象类AbstractLoggerAdapter中的getLogger方法
getLogger()
	1、创建LoggerContext(Log4j2)
	2、调用Log4jLoggerFactory(子类)的newLogger方法,根据LoggerContext生成ExtendedLogger(log4j2用来打印日志的)
	3、使用Log4jLogger封装(转换)ExtendedLogger,返回Log4jLogger的一个实例(也就是slf4j的LoggerFactory生成的Logger)
	备注:AbstractLoggerAdapter里有一个Map,用来存储每个类创建的<LoggerContext(用来生成log4j2的logger),<LogName(日志标识), logger(桥接包中的,slf4j调用该实现)>>
	protected final Map<LoggerContext, ConcurrentMap<String, L>> registry = new WeakHashMap<LoggerContext, ConcurrentMap<String, L>>();
    在执行第二步时,都会查看map中是否存在LoggerContext,如果存在,获取返回,不存在则执行第二三步
*/
    return iLoggerFactory.getLogger(name);
}

1、创建ILoggerFactory 的实现类

//LoggerFactory(slf4j)
public static ILoggerFactory getILoggerFactory() {
/*
  static final int UNINITIALIZED = 0;
  static final int ONGOING_INITIALIZATION = 1;
  static final int FAILED_INITIALIZATION = 2;
  static final int SUCCESSFUL_INITIALIZATION = 3;
  static final int NOP_FALLBACK_INITIALIZATION = 4;

  static int INITIALIZATION_STATE = UNINITIALIZED;
*/
    if (INITIALIZATION_STATE == UNINITIALIZED) {
     //设置为正在初始化状态
      INITIALIZATION_STATE = ONGOING_INITIALIZATION;
      //验证StaticLoggerBinder类(桥接包)是不是log4j2需要的桥接包,正常则设置状态为成功
      performInitialization();
    }
    //判断加载状态
    switch (INITIALIZATION_STATE) {
      case SUCCESSFUL_INITIALIZATION:
      //成功则返回Log4jLoggerFactory
        return StaticLoggerBinder.getSingleton().getLoggerFactory();
      case NOP_FALLBACK_INITIALIZATION: //org/slf4j/impl/StaticLoggerBinder类没有发现异常
      //没有找到适合的StaticLoggerBinder,则出现异常,这个状态返回一个没有实现的NOPLoggerFactory,在getLogger()时返回一个没有实现的Logger,该logger可以正常的调用info这些日志打印方法,但是这些方法都是没有任何实现的
      //目的是程序在缺少对应桥接包的时候,还能够保证业务的正常执行,只是不会打印日志而已
        return NOP_FALLBACK_FACTORY;
      case FAILED_INITIALIZATION: //其他异常
      //直接抛异常,没有捕获则程序中断
        throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
      case ONGOING_INITIALIZATION:
        return TEMP_FACTORY;
    }
    throw new IllegalStateException("Unreachable code");
}
//LoggerFactory
private final static void performInitialization() {
    bind();
    if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
      versionSanityCheck();
    }
}
//
private final static void bind() {
    try {
      Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
      reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
      // the next line does the binding
      StaticLoggerBinder.getSingleton();
      INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
      reportActualBinding(staticLoggerBinderPathSet);
      fixSubstitutedLoggers();
    } catch (NoClassDefFoundError ncde) {
      String msg = ncde.getMessage();
      if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
        INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
        Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
        Util.report("Defaulting to no-operation (NOP) logger implementation");
        Util.report("See " + NO_STATICLOGGERBINDER_URL
                + " for further details.");
      } else {
        failedBinding(ncde);
        throw ncde;
      }
    } catch (java.lang.NoSuchMethodError nsme) {
      String msg = nsme.getMessage();
      if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
        INITIALIZATION_STATE = FAILED_INITIALIZATION;
        Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
        Util.report("Your binding is version 1.5.5 or earlier.");
        Util.report("Upgrade your binding to version 1.6.x.");
      }
      throw nsme;
    } catch (Exception e) {
      failedBinding(e);
      throw new IllegalStateException("Unexpected initialization failure", e);
    }
  }
  • 13
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值