SpringBoot源码解析(十七)ApplicationPreparedEvent

本文分析SpringBoot启动过程中的ApplicationPreparedEvent事件,它跟上文的事件ApplicationContextInitializedEvent一样,都是在prepareContext方法中发布的,同样算是对该方法的补充,正常情况下,接收到该事件的监听器一共有四个
在这里插入图片描述

ConfigFileApplicationListener

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
        }

        if (event instanceof ApplicationPreparedEvent) {
            this.onApplicationPreparedEvent(event);
        }
    }

对于当前事件走第二个分支,进入onApplicationPreparedEvent方法

    private void onApplicationPreparedEvent(ApplicationEvent event) {
        this.logger.switchTo(ConfigFileApplicationListener.class);
        this.addPostProcessors(((ApplicationPreparedEvent)event).getApplicationContext());
    }

调用addPostProcessors方法向容器中添加了一个BeanFactoryPostProcessor

    protected void addPostProcessors(ConfigurableApplicationContext context) {
        context.addBeanFactoryPostProcessor(new ConfigFileApplicationListener.PropertySourceOrderingPostProcessor(context));
    }

具体类型为其内部类PropertySourceOrderingPostProcessor

    private class PropertySourceOrderingPostProcessor implements BeanFactoryPostProcessor, Ordered {
        private ConfigurableApplicationContext context;

        PropertySourceOrderingPostProcessor(ConfigurableApplicationContext context) {
            this.context = context;
        }

        public int getOrder() {
            return -2147483648;
        }

        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            this.reorderSources(this.context.getEnvironment());
        }

        private void reorderSources(ConfigurableEnvironment environment) {
            PropertySource<?> defaultProperties = environment.getPropertySources().remove("defaultProperties");
            if (defaultProperties != null) {
                environment.getPropertySources().addLast(defaultProperties);
            }

        }
    }

前文介绍过,BeanFactoryPostProcessor类型会在后面Spring容器refresh的过程调用,触发其postProcessBeanFactory方法,在该方法中,先尝试从environment删除名为defaultProperties的PropertySource,如果删除成功的话再把它添加到PropertySource列表的末尾

其实就是对defaultProperties的优先级做一个修正,默认情况下,该PropertySource的优先级应该是最低的,但是在前面提供过很多个扩展点,可以对environment做一些定制以及干预,如果在这个过程中破坏了defaultProperties兜底的特性,就在将来执行BeanFactoryPostProcessor的时候对它做一个调整

LoggingApplicationListener

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationStartingEvent) {
            this.onApplicationStartingEvent((ApplicationStartingEvent)event);
        } else if (event instanceof ApplicationEnvironmentPreparedEvent) {
            this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
        } else if (event instanceof ApplicationPreparedEvent) {
            this.onApplicationPreparedEvent((ApplicationPreparedEvent)event);
        } else if (event instanceof ContextClosedEvent && ((ContextClosedEvent)event).getApplicationContext().getParent() == null) {
            this.onContextClosedEvent();
        } else if (event instanceof ApplicationFailedEvent) {
            this.onApplicationFailedEvent();
        }
    }

对于当前事件进入第三个分支,调用onApplicationPreparedEvent方法

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

这个方法判断容器中是否存在名为springBootLoggingSystem的bean,如果不存在的话,就把自己的loggingSystem作为一个单例bean注册到容器中

这个loggingSystem就是当前项目使用的日志体系,是在之前的事件ApplicationStartingEvent中初始化的

    private void onApplicationStartingEvent(ApplicationStartingEvent event) {
        this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
        this.loggingSystem.beforeInitialize();
    }

我们在系列的第三篇文章中已经看过这个过程,就不在赘述了,这里就是把它存到容器的单例池

BackgroundPreinitializer & DelegatingApplicationListener

这两个监听器跟上篇文章完全一样,前者虽然接收了当前事件,但不会做任何处理,后者只是在存在自定义监听器的情况下,将当前事件向自定义监听器传播

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值