完全掌控logging的生与死(一)LoggingApplicationListener

在SpringBoot里面的spring.factories里面有注册一个org.springframework.boot.context.logging.LoggingApplicationListener,这个监听器起到了加载具体的logging的能力。
我们分别看下在sb启动的不同的阶段,此listener所做的事情,在开始启动的阶段,如下

private void onApplicationStartingEvent(ApplicationStartingEvent event) {
                //根据classloader加载日志模块,哪个加载成功,就使用哪个
        this.loggingSystem = LoggingSystem
                .get(event.getSpringApplication().getClassLoader());
               //执行具体的logging组件的回调方法-beforeInitialize
        this.loggingSystem.beforeInitialize();
    }

而对于LoggingSystem.get(event.getSpringApplication().getClassLoader())方法,

    /**
     * Detect and return the logging system in use. Supports Logback and Java Logging.
     * @param classLoader the classloader
     * @return the logging system
     */
    public static LoggingSystem get(ClassLoader classLoader) {
                //是否有自己配置日志模块
        String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
        if (StringUtils.hasLength(loggingSystem)) {
            if (NONE.equals(loggingSystem)) {
                return new NoOpLoggingSystem();
            }
                       //如果有配置,根据配置的loggingSystemClass反射去初始化
            return get(classLoader, loggingSystem);
        }
                //如果没有,那么系统默认按照,logback,log4j,jul的顺序去加载对应的class,哪个加载成功就使用哪个日志模块,我本地使用了logback,故而加载出来loggingSystem就是logback。(slf4j+logback)是spring推荐的标准的logging配置。
        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"));
    }

    private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClass) {
        try {
            Class<?> systemClass = ClassUtils.forName(loggingSystemClass, classLoader);
            return (LoggingSystem) systemClass.getConstructor(ClassLoader.class)
                    .newInstance(classLoader);
        }
        catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

在上一步主要是确定使用的logging组件(一下默认使用的组件是logback),确定了组件之后,接下来就是对选择的组件进行初始化的操作。那在什么时候进行初始话的操作呢,肯定是在所有的系统变量加载完成之后,根据配置的系统变量来对组件进行初始化了。所以初始化发生在如下

private void onApplicationEnvironmentPreparedEvent(
            ApplicationEnvironmentPreparedEvent event) {
        if (this.loggingSystem == null) {
            this.loggingSystem = LoggingSystem
                    .get(event.getSpringApplication().getClassLoader());
        }
        initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
    }

protected void initialize(ConfigurableEnvironment environment,
            ClassLoader classLoader) {
        new LoggingSystemProperties(environment).apply();
        LogFile logFile = LogFile.get(environment);
        if (logFile != null) {
            logFile.applyToSystemProperties();
        } 
                //初始化sb的logging级别
        initializeEarlyLoggingLevel(environment);
                //根据环境变量初始化系统
        initializeSystem(environment, this.loggingSystem, logFile);
                //确定最终的logging等级
        initializeFinalLoggingLevels(environment, this.loggingSystem);
                //注册shutdown的钩子方法
        registerShutdownHookIfNecessary(environment, this.loggingSystem);
    }

第三步,将应用启动起来之后,将loggingSystem作为bean注册到了容器,后期我们会根据这个bean做动态化的扩展和增强(重点打钩)

    private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
        ConfigurableListableBeanFactory beanFactory = event.getApplicationContext()
                .getBeanFactory();
        if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
            beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
        }
    }

而onContextClosedEvent() 和onApplicationFailedEvent可以忽略,主要是应用启动失败的话,调用this.loggingSystem.cleanUp()。做一些清理工作。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容