SpringBoot源码阅读(7)——日志系统加载

SpringBoot的日志系统是在监听器中加载的。
SpringApplication的实例方法run,第298行。

listeners.starting(bootstrapContext, this.mainApplicationClass);

最终触发了监听器LoggingApplicationListener

具体方法逻辑

private void onApplicationStartingEvent(ApplicationStartingEvent event) {
	this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
	this.loggingSystem.beforeInitialize();
}
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
private static final LoggingSystemFactory SYSTEM_FACTORY = LoggingSystemFactory.fromSpringFactories();
public static LoggingSystem get(ClassLoader classLoader) {
	String loggingSystemClassName = System.getProperty(SYSTEM_PROPERTY);
	if (StringUtils.hasLength(loggingSystemClassName)) {
		if (NONE.equals(loggingSystemClassName)) {
			return new NoOpLoggingSystem();
		}
		return get(classLoader, loggingSystemClassName);
	}
	LoggingSystem loggingSystem = SYSTEM_FACTORY.getLoggingSystem(classLoader);
	Assert.state(loggingSystem != null, "No suitable logging system located");
	return loggingSystem;
}

先从环境变量中获取日志配置。
如果有,就用这个全限定类名作为日志系统实例化这个日志系统。
这个类必须是LoggingSystem的子类,否则会报异常。如-Dorg.springframework.boot.logging.LoggingSystem=xxx.xx.xx.XxxLogSystem
如果没有,则从类路径中寻找LoggingSystemFactory的实现类

static LoggingSystemFactory fromSpringFactories() {
	return new DelegatingLoggingSystemFactory(
			(classLoader) -> SpringFactoriesLoader.loadFactories(LoggingSystemFactory.class, classLoader));
}

LoggingSystemFactory的实现类有

# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory

加载后排序,三个类都是被Order注解的

日志系统Order
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
LogbackLoggingSystem.FactoryInteger.MAX_VALUE
最后顺序是
  1. LogbackLoggingSystem.Factory
  2. Log4J2LoggingSystem.Factory
  3. JavaLoggingSystem.Factory

之后在DelegatingLoggingSystemFactorygetLoggingSystem方法中获取日志系统。

@Override
public LoggingSystem getLoggingSystem(ClassLoader classLoader) {
	List<LoggingSystemFactory> delegates = (this.delegates != null) ? this.delegates.apply(classLoader) : null;
	if (delegates != null) {
		for (LoggingSystemFactory delegate : delegates) {
			LoggingSystem loggingSystem = delegate.getLoggingSystem(classLoader);
			if (loggingSystem != null) {
				return loggingSystem;
			}
		}
	}
	return null;
}

从这里可以看出,三个日志系统的优先级顺序:logback > log4j2 > java log

LoggingSystemFactory.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {

	private static final boolean PRESENT = ClassUtils.isPresent("ch.qos.logback.classic.LoggerContext",
			Factory.class.getClassLoader());

	@Override
	public LoggingSystem getLoggingSystem(ClassLoader classLoader) {
		if (PRESENT) {
			return new LogbackLoggingSystem(classLoader);
		}
		return null;
	}

}

判断类路径中是否有ch.qos.logback.classic.LoggerContext,有的话,就创建一个LogbackLoggingSystem对象返回。
默认返回null。

Log4J2LoggingSystem.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {

	private static final boolean PRESENT = ClassUtils
			.isPresent("org.apache.logging.log4j.core.impl.Log4jContextFactory", Factory.class.getClassLoader());

	@Override
	public LoggingSystem getLoggingSystem(ClassLoader classLoader) {
		if (PRESENT) {
			return new Log4J2LoggingSystem(classLoader);
		}
		return null;
	}

}

判断类路径中是否有org.apache.logging.log4j.core.impl.Log4jContextFactory,如果有,就实例化一个Log4J2LoggingSystem对象
默认返回null。

JavaLoggingSystem.Factory

@Order(Ordered.LOWEST_PRECEDENCE)
public static class Factory implements LoggingSystemFactory {

	private static final boolean PRESENT = ClassUtils.isPresent("java.util.logging.LogManager",
			Factory.class.getClassLoader());

	@Override
	public LoggingSystem getLoggingSystem(ClassLoader classLoader) {
		if (PRESENT) {
			return new JavaLoggingSystem(classLoader);
		}
		return null;
	}

}

判断路径中是否存在java.util.logging.LogManager,如果存在,就实例化一个JavaLoggingSystem类。
默认返回null。

不出异常的话,最后总会得到一个日志系统。
然后调用日志系统的beforeInitialize方法。

初始化

LogbackLoggingSystem

@Override
public void beforeInitialize() {
	LoggerContext loggerContext = getLoggerContext();
	if (isAlreadyInitialized(loggerContext)) {
		return;
	}
	super.beforeInitialize();
	loggerContext.getTurboFilterList().add(FILTER);
}
private LoggerContext getLoggerContext() {
	ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
	Assert.isInstanceOf(LoggerContext.class, factory,
			() -> String.format(
					"LoggerFactory is not a Logback LoggerContext but Logback is on "
							+ "the classpath. Either remove Logback or the competing "
							+ "implementation (%s loaded from %s). If you are using "
							+ "WebLogic you will need to add 'org.slf4j' to "
							+ "prefer-application-packages in WEB-INF/weblogic.xml",
					factory.getClass(), getLocation(factory)));
	return (LoggerContext) factory;
}

获取LoggerContext并初始化,具体逻辑是在slf4j,这里不展开。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值