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);
                }
            }
        }
  • 相关阅读:
    父亲节前参考四级考试
    rpm小解
    oracle忘记sys/system/scott用户的密码怎么办
    yum 小解
    linux下设置swap文件
    启动mysql 报错: ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2)
    mysql 常用命令
    wget安装
    删除mysql
    什么是swap分区
  • 原文地址:https://www.cnblogs.com/jhxxb/p/13960012.html
Copyright © 2011-2022 走看看