Spring boot load log module
Spring jcl
Spring jcl is the basic package for spring boot to connect SLF4J. It implements the existence of Log4j 2.x API and SLF4J 1.7 API in the spring framework classpath.
ServiceLoader
Find the implementation class of the interface through configuration, create a new folder services under META-INF of the jar package of the implementation class, and a new file under services, with the fully qualified name of the interface as the file name and the content as the fully qualified name of the implementation class.
Reference link:
https://www.jianshu.com/p/7601ba434ff4
https://blog.csdn.net/shi2huang/article/details/80308531
Log4j get ConfigurationFactory
Core code
String ALL_TYPES = "*"; for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types != null) { for (final String type : types) { // Only XmlConfigurationFactory is eligible if (type.equals(ALL_TYPES)) { final Configuration config = factory.getConfiguration(loggerContext, name, configLocation); if (config != null) { return config; } } } } }
The process of spring boot loading log4j2
Spring boot loading log4j2 is mainly divided into two stages: the first stage is start, and the second stage is initialize
start stage
- The LogAdapter uses Class.forName to load different log implementations and internal classes to call
- Log4j identifies the ConfigurationFactory through the PluginProcess annotation to @ Plugin. For details, refer to the spring boot configuration log4j2 crawl pit
Initialize phase
During initialization, SpringApplicationRunListeners of the SpringApplication.run() method
- beforeInitialize() to determine whether to bridge with slf4j.
if (isBridgeJulIntoSlf4j()) { removeJdkLoggingBridgeHandler(); SLF4JBridgeHandler.install(); } // Classutils. Ispresent() spring implements similar Class.forName functions ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
- LoggingApplicationListener code configuration onApplicationEvent
public void onApplicationEvent(ApplicationEvent event) { // Beforeinitialize stage if (event instanceof ApplicationStartingEvent) { onApplicationStartingEvent((ApplicationStartingEvent) event); } // Environment configuration, i.e. initializing stage else if (event instanceof ApplicationEnvironmentPreparedEvent) { onApplicationEnvironmentPreparedEvent( (ApplicationEnvironmentPreparedEvent) event); } // After the program runs, call the log phase else if (event instanceof ApplicationPreparedEvent) { onApplicationPreparedEvent((ApplicationPreparedEvent) event); } // Program close else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event) .getApplicationContext().getParent() == null) { onContextClosedEvent(); } // fail else if (event instanceof ApplicationFailedEvent) { onApplicationFailedEvent(); } }
- Log4j2 determines whether the log is the same instance, and uses identityHashCoder to make identity hash and duplicate judgment for AppClassLoader
- Shutdown hook learning (have time to study)
private void registerShutdownHookIfNecessary(Environment environment, LoggingSystem loggingSystem) { boolean registerShutdownHook = environment .getProperty(REGISTER_SHUTDOWN_HOOK_PROPERTY, Boolean.class, false); if (registerShutdownHook) { Runnable shutdownHandler = loggingSystem.getShutdownHandler(); if (shutdownHandler != null && shutdownHookRegistered.compareAndSet(false, true)) { registerShutdownHook(new Thread(shutdownHandler)); } } } void registerShutdownHook(Thread shutdownHook) { Runtime.getRuntime().addShutdownHook(shutdownHook); }