zoukankan      html  css  js  c++  java
  • Spring IOC 初始化刷新流程七八九十:initMessageSource()、initApplicationEventMulticaster()、onRefresh()、registerListeners()

    Spring IOC 初始化刷新流程:https://www.cnblogs.com/jhxxb/p/13609289.html

    方法源码

    initMessageSource()

    初始化消息源,向容器里注册一个事件源的单例 Bean:MessageSource

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
        protected void initMessageSource() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            // 判断是否已经存在名为 “messageSource” 的 Bean 了(一般情况下是没有的)
            if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
                // 从容器里拿出这个 messageSource
                this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
                // Make MessageSource aware of parent MessageSource.
                // 设置父属性
                if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                    HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                    if (hms.getParentMessageSource() == null) {
                        // Only set parent context as parent MessageSource if no parent MessageSource registered already.
                        hms.setParentMessageSource(getInternalParentMessageSource());
                    }
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("Using MessageSource [" + this.messageSource + "]");
                }
            } else {
                // Use empty MessageSource to be able to accept getMessage calls.
                DelegatingMessageSource dms = new DelegatingMessageSource();
                // 其实就是获取到父容器的 messageSource 字段(否则就是 getParent() 上下文自己)
                dms.setParentMessageSource(getInternalParentMessageSource());
                // 给当前的 messageSource 赋值
                this.messageSource = dms;
                // 把 messageSource 作为一个单例的 Bean 注册进 beanFactory 工厂里
                beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
                if (logger.isTraceEnabled()) {
                    logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
                }
            }
        }

    initApplicationEventMulticaster()

    初始化事件多播器:ApplicationEventMulticaster

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
        protected void initApplicationEventMulticaster() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            // 若用户自己定义了这个 Bean(名称必须是 "applicationEventMulticaster"),就以用户的为准。
            // 否则注册一个系统默认的 SimpleApplicationEventMulticaster
            if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
                this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
                if (logger.isTraceEnabled()) {
                    logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
                }
            } else {
                this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
                if (logger.isTraceEnabled()) {
                    logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
                }
            }
        }

    onRefresh()

    public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext implements ConfigurableWebApplicationContext, ThemeSource {
        @Override
        protected void onRefresh() {
            // 模版方法。本环境中的实现为:AbstractRefreshableWebApplicationContext#onRefresh 方法,Web 环境,所以去初始化了它的主题
            this.themeSource = UiApplicationContextUtils.initThemeSource(this);
        }

    registerListeners()

    上面已经把事件源、多播器都注册好了,这里就是注册监听器了

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
        protected void registerListeners() {
            // Register statically specified listeners first.
            // 这一步和手动注册 BeanDefinitionRegistryPostProcessor 一样,可以自己通过 set 手动注册监听器,然后是最先执行的(此处我们没有自己set)
            for (ApplicationListener<?> listener : getApplicationListeners()) {
                // 把手动注册的监听器绑定到广播器
                getApplicationEventMulticaster().addApplicationListener(listener);
            }
    
            // Do not initialize FactoryBeans here: We need to leave all regular beans uninitialized to let post-processors apply to them!
            // 取到容器里面的所有的监听器的名称,绑定到广播器,后面会广播出去这些事件
            // 注意:此处并没有说到 ApplicationListenerDetector
            String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
            for (String listenerBeanName : listenerBeanNames) {
                getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
            }
    
            // Publish early application events now that we finally have a multicaster...
            // 这一步需要注意:如果存在早期应用事件,这里就直接发布了(同时就把 earlyApplicationEvents 字段置为 null)
            Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
            this.earlyApplicationEvents = null;
            if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
                for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                    getApplicationEventMulticaster().multicastEvent(earlyEvent);
                }
            }
        }
  • 相关阅读:
    Java重温学习笔记,Java8新特性:函数式接口
    Java重温学习笔记,Java8新特性:Lambda 表达式
    236. 二叉树的最近公共祖先
    230. 二叉搜索树中第K小的元素
    117. 填充每个节点的下一个右侧节点指针 II
    116. 填充每个节点的下一个右侧节点指针
    111. 二叉树的最小深度
    109. 有序链表转换二叉搜索树
    剑指 Offer 68
    1367. 二叉树中的列表
  • 原文地址:https://www.cnblogs.com/jhxxb/p/13960012.html
Copyright © 2011-2022 走看看