Spring IoC源码学习:finishRefresh 详解

简介: Spring IoC 的核心内容已经介绍完毕,本文将对最后一个方法 finishRefresh 进行介绍。由于存在上下文关系,本文也会对 initApplicationEventMulticaster 方法、registerListeners 方法进行介绍。

目录

Spring IoC源码学习全系列

前言

正文

代码块1initApplicationEventMulticaster

代码块2registerListeners

代码块3finishRefresh

代码块4initLifecycleProcessor

代码块5onRefresh

代码块6publishEvent

代码块7multicastEvent

代码块8invokeListener

自定义监听器实现

总结

相关文章


Spring IoC源码学习全系列

小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习ApplicationContext刷新前的配置

Spring IoC源码学习obtainFreshBeanFactory详解

Spring IoC源码学习parseDefaultElement详解

Spring IoC源码学习parseCustomElement详解

Spring IoC源码学习:context:component-scan节点详解

Spring IoC源码学习invokeBeanFactoryPostProcessors详解

Spring IoC源码学习registerBeanPostProcessors详解

Spring IoC源码学习finishBeanFactoryInitialization详解

Spring IoC源码学习getBean详解

Spring IoC源码学习createBean详解(上)

Spring IoC源码学习createBean详解(下)

Spring IoC源码学习:@Autowire 详解

Spring IoC源码学习:finishRefresh 详解

 

前言


Spring IoC 的核心内容已经介绍完毕,本文将对最后一个方法 finishRefresh 进行介绍。由于存在上下文关系,本文也会对 initApplicationEventMulticaster 方法、registerListeners 方法进行介绍。

 

正文


首先,我们回到 refresh 方法。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            // Initialize message source for this context.
            initMessageSource();
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
            // Initialize other special beans in specific context subclasses.
            onRefresh();
            // Check for listener beans and register them.
            registerListeners();
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
            // Last step: publish corresponding event.
            finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            // Reset 'active' flag.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

initApplicationEventMulticaster():初始化应用的事件广播器,见代码块1详解

registerListeners():注册监听器,见代码块2详解

finishRefresh():完成上下文的刷新工作,见代码块3详解

 

代码块1initApplicationEventMulticaster

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 1.判断BeanFactory是否已经存在事件广播器(固定使用beanName=applicationEventMulticaster)
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        // 1.1 如果已经存在,则将该bean赋值给applicationEventMulticaster
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    } else {
        // 1.2 如果不存在,则使用SimpleApplicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        // 并将SimpleApplicationEventMulticaster作为默认的事件广播器,注册到BeanFactory中
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                    APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                    "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

内容比较简单,就是要初始化应用的事件广播器。通过之前的学习我们知道,在 Spring 中,有一些内部的 bean 会使用固定的 beanName,这边的事件广播器就是这样,固定使用 beanName applicationEventMulticaster


具体的,如果当前 BeanFactory 中已经存在 beanName = applicationEventMulticaster bean 实例或者 BeanDefinition,那么就使用该 bean 作为 applicationEventMulticaster


否则,新建一个默认的事件广播器 SimpleApplicationEventMulticaster 作为 applicationEventMulticaster,并且会注册到 BeanFactory 中。

 

代码块2registerListeners

protected void registerListeners() {
    // Register statically specified listeners first.
    // 1.通过硬编码调用addApplicationListener方法添加的监听器处理(可以通过自定义ApplicationContextInitializer添加)
    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!
    // 2.通过配置文件或注解注入BeanFactory的监听器处理
    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...
    // 3.使用事件广播器,发布早期应用程序事件到相应的监听器
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

1.通过硬编码调用 addApplicationListener 方法添加的监听器处理,可以通过自定义ApplicationContextInitializer 添加,关于自定义 ApplicationContextInitializer 请见Spring IoCApplicationContext刷新前的配置中的代码块12

 

代码块3finishRefresh

protected void finishRefresh() {
    // Initialize lifecycle processor for this context.
    // 1.为此上下文初始化生命周期处理器
    initLifecycleProcessor();
    // Propagate refresh to lifecycle processor first.
    // 2.首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法)
    getLifecycleProcessor().onRefresh();
    // Publish the final event.
    // 3.推送上下文刷新完毕事件到相应的监听器
    publishEvent(new ContextRefreshedEvent(this));
    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

1.为此上下文初始化生命周期处理器,见代码块4详解

2.首先将刷新完毕事件传播到生命周期处理器,见代码块5详解

3.推送上下文刷新完毕事件到相应的监听器,见代码块6详解

 

代码块4initLifecycleProcessor

protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 1.判断BeanFactory是否已经存在生命周期处理器(固定使用beanName=lifecycleProcessor)
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        // 1.1 如果已经存在,则将该bean赋值给lifecycleProcessor
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
        }
    } else {
        // 1.2 如果不存在,则使用DefaultLifecycleProcessor
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        // 并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate LifecycleProcessor with name '" +
                    LIFECYCLE_PROCESSOR_BEAN_NAME +
                    "': using default [" + this.lifecycleProcessor + "]");
        }
    }
}

初始化生命周期处理器,过程同代码块1类似,优先使用用户自定义的生命周期处理器;如果用户没有自定义,则使用默认的DefaultLifecycleProcessor

 

代码块5onRefresh

@Override
public void onRefresh() {
    startBeans(true);
    this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
    // 1.获取所有的Lifecycle bean
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    // 将Lifecycle bean 按阶段分组,阶段通过实现Phased接口得到
    Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
    // 2.遍历所有Lifecycle bean,按阶段值分组
    for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
        Lifecycle bean = entry.getValue();
        // autoStartupOnly=true代表是ApplicationContext刷新时容器自动启动;autoStartupOnly=false代表是通过显示的调用启动
        // 3.当autoStartupOnly=false,也就是通过显示的调用启动,会触发全部的Lifecycle;
        // 当autoStartupOnly=true,也就是ApplicationContext刷新时容器自动启动,只会触发isAutoStartup方法返回true的SmartLifecycle
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            // 3.1 获取bean的阶段值(如果没有实现Phased接口,则值为0)
            int phase = getPhase(bean);
            // 3.2 拿到存放该阶段值的LifecycleGroup
            LifecycleGroup group = phases.get(phase);
            if (group == null) {
                // 3.3 如果该阶段值的LifecycleGroup为null,则新建一个
                group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                phases.put(phase, group);
            }
            // 3.4 将bean添加到该LifecycleGroup
            group.add(entry.getKey(), bean);
        }
    }
    // 4.如果phases不为空
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<Integer>(phases.keySet());
        // 4.1 按阶段值进行排序
        Collections.sort(keys);
        // 4.2 按阶段值顺序,调用LifecycleGroup中的所有Lifecycle的start方法
        for (Integer key : keys) {
            phases.get(key).start();
        }
    }
}

这边讲下 autoStartupOnly 这个参数。


autoStartupOnly = true 时,代表这次刷新是 ApplicationContext刷新时容器自动启动,在这个阶段只会触发 SmartLifecycle,并且要求 SmartLifecycle isAutoStartup() 方法必须返回 true


autoStartupOnly = false,代表这次刷新是通过显示的调用启动,会触发所有的 Lifecycle


这边还引入了 Phased 接口,这个接口类似于 Ordered 接口,只有一个方法用于返回一个阶段值,范围为 Integer.MIN_VALUE ~ Integer.MAX_VALUE。在启动过程,阶段值小的会被优先调用,而在关闭过程,阶段值大的会被优先调用。

 

代码块6publishEvent

@Override
public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }
    // Decorate event as an ApplicationEvent if necessary
    // 1.如有必要,将事件装饰为ApplicationEvent
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    } else {
        applicationEvent = new PayloadApplicationEvent<Object>(this, event);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
        }
    }
    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    } else {
        // 2.使用事件广播器广播事件到相应的监听器
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }
    // Publish event via parent context as well...
    // 3.同样的,通过parent发布事件......
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        } else {
            this.parent.publishEvent(event);
        }
    }
}

2.使用事件广播器广播事件到相应的监听器,见代码块7详解

 

代码块7multicastEvent

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    // 1.getApplicationListeners:返回与给定事件类型匹配的应用监听器集合
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        // 2.返回此广播器的当前任务执行程序
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    // 3.1 executor不为null,则使用executor调用监听器
                    invokeListener(listener, event);
                }
            });
        } else {
            // 3.2 否则,直接调用监听器
            invokeListener(listener, event);
        }
    }
}

3.2 调用监听器,见代码块8详解

 

代码块8invokeListener

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    // 1.返回此广播器的当前错误处理程序
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        try {
            // 2.1 如果errorHandler不为null,则使用带错误处理的方式调用给定的监听器
            doInvokeListener(listener, event);
        } catch (Throwable err) {
            errorHandler.handleError(err);
        }
    } else {
        // 2.2 否则,直接调用调用给定的监听器
        doInvokeListener(listener, event);
    }
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        // 触发监听器的onApplicationEvent方法,参数为给定的事件
        listener.onApplicationEvent(event);
    } catch (ClassCastException ex) {
        String msg = ex.getMessage();
        if (msg == null || msg.startsWith(event.getClass().getName())) {
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            Log logger = LogFactory.getLog(getClass());
            if (logger.isDebugEnabled()) {
                logger.debug("Non-matching event type for listener: " + listener, ex);
            }
        } else {
            throw ex;
        }
    }
}

自定义监听器实现


如果我们想在 Spring IoC 容器构建完毕之后进行一些逻辑,就可以通过监听器来实现。

创建一个自定义监听器,实现 ApplicationListener 接口,监听 ContextRefreshedEvent(上下文刷新完毕事件),并且将该监听器注册到 Spring IoC容器即可。

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
/**
 * @author joonwhee
 * @date 2019/6/22
 */
@Component
public class MyRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 自己的逻辑处理
    }
}

这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到MyRefreshedListener 中。


ContextRefreshedEvent 相似的还有:ContextStartedEventContextClosedEventContextStoppedEvent,有兴趣的可以自己看看这几个事件的使用场景。


当然,我们也可以自定义监听事件,只需要继承 ApplicationContextEvent 抽象类即可。

 

总结


本文主要介绍了几个用于扩展使用的功能:


·       ApplicationEventMulticaster:应用事件广播器,用于发布事件到相应的监听器。

·       LifecycleProcessor:生命周期处理器,用于处理生命周期事件。

·       Lifecycle:定义生命周期控制方法的接口,特别是 SmartLifecycle,可以


Spring IoC 容器刷新完毕时进行触发。

·       ApplicationContextEvent:应用事件的基类。

·       ApplicationListener,应用事件监听器,用于监听应用事件。

 

 

相关文章
|
21天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
21天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
119 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
8天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
5天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
15 4
|
11天前
|
XML 缓存 Java
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
39 10
|
11天前
|
XML 存储 Java
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
|
9天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
30 3
|
10天前
|
XML 存储 Java
Spring-源码深入分析(二)
Spring-源码深入分析(二)
|
10天前
|
XML 设计模式 Java
Spring-源码深入分析(一)
Spring-源码深入分析(一)
|
8天前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
下一篇
无影云桌面