springboot默认日志框架选择源码解析(推荐)

2025-05-29 0 60

背景:

今天新生成一个springboot项目,然而启动日志,还有mybatis的详细日志无法打印出来,自写程序中打印的日志可以输出;网上找了很多资料,都没法解决问题;于是决定跟一下源码,弄清springboot日志相关的逻辑。

环境配置:macbook; intellij idea community edition 2020.03 ; gradle 6.8.3 jdk1.8 ;

gradle引用包如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18
dependencies {

compile "com.alibaba:fastjson:1.2.75"

compile "mysql:mysql-connector-java"

//spring

compile("org.springframework.boot:spring-boot-starter")

compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4")

compile("org.springframework.boot:spring-boot-starter-web")

compile("org.springframework.boot:spring-boot-starter-actuator")

//lombok

compileOnly 'org.projectlombok:lombok'

annotationProcessor 'org.projectlombok:lombok'

//test

testCompile('org.springframework.boot:spring-boot-starter-test')

testImplementation 'io.projectreactor:reactor-test'

}

springboot 默认日志使用的是logback(引入spring-boot-starter包后,就自动引入了logback-core,logback-classic两个包,当然还有slf4j的包),当springboot启动时,org.springframework.boot.context.logging.LoggingApplicationListener,该类211行注册的监控事件会被ApplicationStartingEvent触发;如下代码所示,会调用onApplicationStartingEvent初始化loggingSystem,而使用哪个日志组件,就要看loggingSystem初始化的值了

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24
@Override

public void onApplicationEvent(ApplicationEvent event) {

if (event instanceof ApplicationStartingEvent) {

onApplicationStartingEvent((ApplicationStartingEvent) event);

}

else if (event instanceof ApplicationEnvironmentPreparedEvent) {

onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);

}

else if (event instanceof ApplicationPreparedEvent) {

onApplicationPreparedEvent((ApplicationPreparedEvent) event);

}

else if (event instanceof ContextClosedEvent

&& ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {

onContextClosedEvent();

}

else if (event instanceof ApplicationFailedEvent) {

onApplicationFailedEvent();

}

}

private void onApplicationStartingEvent(ApplicationStartingEvent event) {

this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());

this.loggingSystem.beforeInitialize();

}

如下图是org.springframework.boot.logging.LoggingSystem类里面get函数的内容:首先会从system.getProperty中获取className,新生成的项目,取到的这个值都为空,SYSTEM_PROPERTY是一个固定值,就是该类的名字;那么loggingSystem的值就是从SYSTEM_FACTORY.getLoggingSystem(classLoader);获取到的;接下来我们得看LoggingSystemFactory.fromSpringFactories.getLoggingSystem取的值是什么了;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26
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;

}

private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClassName) {

try {

Class<?> systemClass = ClassUtils.forName(loggingSystemClassName, classLoader);

Constructor<?> constructor = systemClass.getDeclaredConstructor(ClassLoader.class);

constructor.setAccessible(true);

return (LoggingSystem) constructor.newInstance(classLoader);

}

catch (Exception ex) {

throw new IllegalStateException(ex);

}

}

LoggingSystemFactory是一个接口,它的实现类在spring-boot-start有4个,其中3个是在内部内类实现,DelegatingLoggingSystemFactory(JavaLoggingSystem,Log4J2LoggingSystem,LogbackLoggingSystem,内部类实现)。上面SYSTEM_FACTORY的实现就是DelegatingLoggingSystemFactory这个类,如下代码中delegates的值为JavaLoggingSystem,Log4J2LoggingSystem,LogbackLoggingSystem;三个类具体的加载逻辑在SpringFactoriesLoader.loadFactories函数中,最终返回的loggingSystem就是前面函数返回列表中的第一个;SpringFactoriesLoader.loadFactories 才是决定springboot默认会使用哪个日志组件关键:该类是spring的核心组件类,在spring-core包中,org.springframework.core.io.support.SpringFactoriesLoader;loggingSystem的值=LogbackLoggingSystem

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47
public interface LoggingSystemFactory {

/**

* Return a logging system implementation or {@code null} if no logging system is

* available.

* @param classLoader the class loader to use

* @return a logging system

*/

LoggingSystem getLoggingSystem(ClassLoader classLoader);

/**

* Return a {@link LoggingSystemFactory} backed by {@code spring.factories}.

* @return a {@link LoggingSystemFactory} instance

*/

static LoggingSystemFactory fromSpringFactories() {

return new DelegatingLoggingSystemFactory(

(classLoader) -> SpringFactoriesLoader.loadFactories(LoggingSystemFactory.class, classLoader));

}

}

class DelegatingLoggingSystemFactory implements LoggingSystemFactory {

private final Function<ClassLoader, List<LoggingSystemFactory>> delegates;

/**

* Create a new {@link DelegatingLoggingSystemFactory} instance.

* @param delegates a function that provides the delegates

*/

DelegatingLoggingSystemFactory(Function<ClassLoader, List<LoggingSystemFactory>> delegates) {

this.delegates = delegates;

}

@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;

}

}

总结:虽然springboot会加载JavaLoggingSystem,Log4J2LoggingSystem,LogbackLoggingSystem三个日志实现类,但在选择时,还是会使用LogbackLoggingSystem作为它的日志框架

到此这篇关于springboot默认日志框架选择源码解析的文章就介绍到这了,更多相关springboot日志框架内容请搜索快网idc以前的文章或继续浏览下面的相关文章希望大家以后多多支持快网idc!

原文链接:https://www.cnblogs.com/deng-1024/p/14525895.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 springboot默认日志框架选择源码解析(推荐) https://www.kuaiidc.com/108230.html

相关文章

发表评论
暂无评论