This article describes how Spring-boot automatically loads the log-related processing classes to facilitate clearer configuration of configuration files during coding.

Log module loading mode

Spring-boot relies on the Event listener to load related components. Main listeners to LoggingApplicationListener then let us see how LoggingApplicationListener together step by step load.

loadingLoggingSystem

LoggingSystem is an abstract class that is primarily responsible for bridging other logging systems. It itself provides a public static method to load LoggingSystem implementation classes, which are also spring-boot implemented. However, he will determine which LoggingSystem implementation class to load based on whether the main classes of other logging systems can be loaded in the current classloader environment. According to the source code, we can find the following correspondence

systems.put("ch.qos.logback.core.Appender"."org.springframework.boot.logging.logback.LogbackLoggingSystem");
	
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory"."org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
                                
systems.put("java.util.logging.LogManager"."org.springframework.boot.logging.java.JavaLoggingSystem");
Copy the code

Based on the above mapping, we can see that LogbackLoggingSystem is used to implement the class as long as our current class loader can load the Appender. The specific logic is as follows

public static LoggingSystem get(ClassLoader classLoader) {
        String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
        if (StringUtils.hasLength(loggingSystem)) {
                if (NONE.equals(loggingSystem)) {
                        return new NoOpLoggingSystem();
                }
                return get(classLoader, loggingSystem);
        }
        return SYSTEMS.entrySet().stream()
        .filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
        .map((entry) -> get(classLoader, entry.getValue()))
        .findFirst()
        .orElseThrow(() -> new IllegalStateException("No suitable logging system located"));
}
Copy the code

Attentive students may be found, in fact, we can also specify system properties (org. Springframework. Boot. Logging. LoggingSystem) to inform the spring which implementation class should be loaded, and here you can write custom implementation class.

LogbackLoggingSystem

Here we take LogbackLoggingSystem as an example to analyze the subsequent log loading logic of Spring-boot.

When it’s loaded into LogbackLoggingSystem it first calls the beforeInitialize method, which basically loads the LoggerContext, so notice here, LoggerFactory is not a logback LoggerContext… This is where it comes from

The Loggback normal JAR package depends on the Logback-classic SLf4J-API

private LoggerContext getLoggerContext(a) {
    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;
    }
Copy the code

Initialize the log system

When LoggingSystem is loaded, initialize the log system

protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
    // Add log properties to the system. property
    new LoggingSystemProperties(environment).apply();
    Logfile.file_name_property = logging.file.name logging.file.path
    this.logFile = LogFile.get(environment);
    if (this.logFile ! =null) {
            this.logFile.applyToSystemProperties();
    }
    / / add the default logger (web, SQL) LoggingApplicationListener. DEFAULT_GROUP_LOGGERS
    this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);
    initializeEarlyLoggingLevel(environment);
    / / initialize loggingsystem configuration, including: logging configuration file path (LoggingApplicationListener. CONFIG_PROPERTY = logging.)
    // Default: "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml"
    initializeSystem(environment, this.loggingSystem, this.logFile);
    LogLevel(LOGGING_LEVEL=logging.level) LogLevel(LOGGING_LEVEL=logging.level)
    initializeFinalLoggingLevels(environment, this.loggingSystem);
    // Configure the shutdown hook (REGISTER_SHUTDOWN_HOOK_PROPERTY = "logging.register.register-shutdown-hook ")
    registerShutdownHookIfNecessary(environment, this.loggingSystem);
}
Copy the code

Register objects such as LoggingSystem with the Spring container

if(! beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) { beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME,this.loggingSystem);
}
if (this.logFile ! =null && !beanFactory.containsBean(LOG_FILE_BEAN_NAME)) {
    beanFactory.registerSingleton(LOG_FILE_BEAN_NAME, this.logFile);
}
if (this.loggerGroups ! =null && !beanFactory.containsBean(LOGGER_GROUPS_BEAN_NAME)) {
    beanFactory.registerSingleton(LOGGER_GROUPS_BEAN_NAME, this.loggerGroups);
}
Copy the code

conclusion

By default, Spring-boot will automatically assemble the corresponding logging system with the logging framework we rely on. We just need to know how to use the configuration to achieve the results we want. For example, the common configurations are as follows

  • Logging. level Configures the log level
  • Logging. Config configuration Configuration file addresses are generally:classpath:logback-debug.xml
  • Logback automatically loads by defaultlogback.xmlThe configuration file

Thank you

Welcome to comment! Content is updated continuously!