【SpringBoot】【六】 刷新上下文

1  前言

上节我们看了上下文的创建和准备,那么我们这节就来看看刷新上下文。

2  刷新上下文

首先就是我们的 run 方法,执行刷新上下文  refreshContext(context):

// ###run方法
refreshContext(context);
// ###SpringApplication
private void refreshContext(ConfigurableApplicationContext context) {
    // 上下文的刷新
    refresh(context);
    // 注册关闭钩子
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}
protected void refresh(ApplicationContext applicationContext) {
    // 判断当前的上下文是不是 AbstractApplicationContext类型的
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    // 转换并刷新
    ((AbstractApplicationContext) applicationContext).refresh();
}
// ###ServletWebServerApplicationContext
@Override
public final void refresh() throws BeansException, IllegalStateException {
    try {
        // 父类的刷新即AbstractApplicationContext
        super.refresh();
    }
    catch (RuntimeException ex) {
        // 刷新异常的话停止Web容器比如tomcat
        stopAndReleaseWebServer();
        throw ex;
    }
}

刷新的核心方法,调用的是AbstractApplicationContextrefresh方法,该方法中又调用了十多个方法,这是刷新上下文的核心代码,总的流程如下:

// ### AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 启动步骤标记
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        // 准备刷新 Prepare this context for refreshing.
        prepareRefresh();
        // 通知子类刷新内部bean工厂 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.
            // Bean工厂后置处理
            postProcessBeanFactory(beanFactory);
            // 步骤标记
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Invoke factory processors registered as beans in the context.
            // 执行Bean工厂后置处理 核心大哥有个是ConfigurationClassPostProcessor @Configuration @ComponentScan都是这大哥
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注册Bean 后置处理器 Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            // 国际化 Initialize message source for this context.
            initMessageSource();
            // 注册事件发布器 Initialize event multicaster for this context.
            initApplicationEventMulticaster();
            // Initialize other special beans in specific context subclasses.
            // 这里对于SpringBoot主要就是创建WebServer
            onRefresh();
            // 注册监听器 Check for listener beans and register them.
            registerListeners();
            // 初始化非延迟加载Bean 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);
            }
            // 销毁Bean 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();
            // 上下文刷新结束
            contextRefresh.end();
        }
    }
}

那我们一一来看下哈。

2.1  prepareRefresh 准备刷新

prepareRefresh准备刷新方法主要作用就是初始化一些状态和属性以及打印一些日志,检验一些属性:

protected void prepareRefresh() {
    // Switch to active.
    // 开始时间
    this.startupDate = System.currentTimeMillis();
    // 设置关闭状态为 false
    this.closed.set(false);
    // 设置激活状态为 true
    this.active.set(true);
    // 打印日志
    if (logger.isDebugEnabled()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
        }
        else {
            logger.debug("Refreshing " + getDisplayName());
        }
    }
    // 初始化一些属性资源 Initialize any placeholder property sources in the context environment.
    initPropertySources();
    // 查看属性解析器是否配置了必须配置的属性,如果有设置,又在属性源中没配置,则会抛出 MissingRequiredPropertiesException
    // Validate that all properties marked as required are resolvable:
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();
    // Store pre-refresh ApplicationListeners...
    if (this.earlyApplicationListeners == null) {
        // 所有的监听器赋值给 earlyApplicationListeners
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        // 存在则清理完再添加 Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }
    // 所有的事件初始化为空
    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

2.2  获取工厂

obtainFreshBeanFactory,只是将DefaultListableBeanFactory Bean 工厂刷新状态为已刷新,设置一个ID,然后返回等待进行下一步处理:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // DefaultListableBeanFactory 设置状态和ID
    refreshBeanFactory();
    return getBeanFactory();
}
protected final void refreshBeanFactory() throws IllegalStateException {
    //  更新this.refreshed字段为true, 表示已刷新
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    // 设置一个 ID => getId()为应用名(比如:demoApplication)给Bean 工厂
    this.beanFactory.setSerializationId(getId());
}

2.3  刷新上下文

获取到Bean 工厂后,开始准备Bean 工厂,主要是进行功能扩展,逻辑如下所示:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置类加载器:存在则直接设置不存在则用默认类加载器 Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置SPEL 表达式解析器
    if (!shouldIgnoreSpel) {
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }
    // 设置属性注册解析器PropertyEditor
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // Configure the bean factory with context callbacks.
    // 添加Bean后置处理器  ApplicationContextAwareProcessor
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 设置忽略自动装配的接口
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
    // 设置可以自动装配的接口
    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 添加Bean 后置处理器 ApplicationListenerDetector Register early post-processor for detecting inner beans as Applicatio
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    //  LoadTimeWeaver AOP 处理,增加 AspectJ 的支持 Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 将environment、systemProperties、systemEnvironment、applicationStartup 注册到工厂中 Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
    if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
        beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
    }
}

2.4  Bean 工厂后置处理

postProcessBeanFactory方法中,主要是添加了一个BeanPostProcessor以及注册作用域:

// ### ServletWebServerApplicationContext
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 添加用于处理WebApplicationContextServletContextAware接口的processor
    beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
    // 忽略自动装配接口 ServletContextAware
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    // 注册了web的scope作用域,这里有request、session、application
    registerWebApplicationScopes();
}
private void registerWebApplicationScopes() {
    ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
    WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
    existingScopes.restore();
}
/** ### WebApplicationContextUtils spring-web中的
 * Register web-specific scopes ("request", "session", "globalSession", "application")
 * with the given BeanFactory, as used by the WebApplicationContext.
 * @param beanFactory the BeanFactory to configure
 * @param sc the ServletContext that we're running within
 */
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
        @Nullable ServletContext sc) {
    beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
    beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
    if (sc != null) {
        ServletContextScope appScope = new ServletContextScope(sc);
        beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
        // Register as ServletContext attribute, for ContextCleanupListener to detect it.
        sc.setAttribute(ServletContextScope.class.getName(), appScope);
    }
    beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
    beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
    if (jsfPresent) {
        FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
    }
}

2.5  执行 Bean工厂后置处理器

invokeBeanFactoryPostProcessors从字面上理解是执行Bean 工厂后置处理器的意思,这里和Spring 核心功能有关,执行逻辑非常多。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 委托 PostProcessorRegistrationDelegate 来去循环执行每个后置处理
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    //  存在 loadTimeWeaver 时,添加临时的类加载器 Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

整个过程需要复杂,是属于Spring IOC 的范畴,这里只需要记住ConfigurationClassPostProcessor即可,可以看到经过该方法处理过,加载了很多beanDefinition。由于后置处理器非常多 我在看@Configuration @ComponentScan原理的时候,都是 ConfigurationClassPostProcessor 这位大哥做的,这里就不每个后置处理细说了哈。

2.6  注册Bean 后置处理器

PostProcessorRegistrationDelegate.registerBeanPostProcessors方法注册Bean 后置处理器,主要是将这些后置处理器进行分类,并添加到Bean 工厂中:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 委托 PostProcessorRegistrationDelegate 注册Bean 后置处理器
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// 获取BeanPostProcessor 实例中的所有名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 分类存放
    // 实现了PriorityOrdered接口
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    // 实现了MergedBeanDefinitionPostProcessor接口
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    // 实现了Ordered接口
    List<String> orderedPostProcessorNames = new ArrayList<>();
    // 没有实现排序接口
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    // 进行分类处理
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 添加到Bean工厂
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    ...
}

2.7  国际化

接着进入initMessageSource进行国际化处理,如果没有配置国际化,默认使用的是DelegatingMessageSource

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);
        // 如果父级容器不空,并且 MessageSource是 HierarchicalMessageSource类型 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. 如果 HierarchicalMessageSource 没有父级消息源,则设置
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // 不包含,MessageSource类型的 Bean ,创建一个DelegatingMessageSource  Use empty MessageSource to be able to accept getMessage calls.
        DelegatingMessageSource dms = new DelegatingMessageSource();
        // 设置父级消息源
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        // 将 messageSource注册到Bean工厂中
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
        }
    }
}

另外提一下 MessageSource spring-context模块提供的接口,它的作用是提供信息的国际化和包含参数的信息的替换,还提供了HierarchicalMessageSource接口,可以分层次地解析消息。

public interface MessageSource {
    // 解析code对应的信息进行返回,如果对应的code不能被解析则返回默认信息defaultMessage。
    @Nullable
    String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
    // 解析code对应的信息进行返回,如果对应的code不能被解析则抛出异常NoSuchMessageException
    String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
    // 通过传递的MessageSourceResolvable对应来解析对应的信息
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}

2.8  注册事件发布器

initApplicationEventMulticaster,先查看是否有自己注册ApplicationEventMulticaster 类型的Bean 定义,没有的话,注册一个默认的。

protected void initApplicationEventMulticaster() {
    // 获取bean工厂
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 判断是否有用户自定义的广播器 applicationEventMulticaster
    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() + "]");
        }
    }
}

ApplicationEventMulticaster是事件发布器,由它进行事件的派发。

2.9  刷新-创建WebServer

onRefresh()方法中,主要是创建并启动 Web 服务。

protected void onRefresh() {
    // 调用父类的刷新
    super.onRefresh();
    try {
        // 创建 Web 服务
        createWebServer();
    }
    catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}
private void createWebServer() {
    // 这里初始都为NULL
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        // 工厂模式 默认获取的是 TomcatServletWebServerFactory
        ServletWebServerFactory factory = getWebServerFactory();
        // 获取 TomcatWebServer,实例化Tomcat
        this.webServer = factory.getWebServer(getSelfInitializer());
    }
    else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context", ex);
        }
    }
    // 加载Servlet 属性源
    initPropertySources();
}

版本高的会有NettyServerFactory的哈。

2.10  注册监听器

registerListeners()主要是将监听器注册到ApplicationEventMulticaster事件发布器中:

protected void registerListeners() {
    // 将监听器添加到事件发布器中applicationEventMulticaster Register statically specified listeners first.
    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!
    // 将注入的listener bean维护到applicationEventMulticaster中
    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...
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

2.11  初始化非延迟加载Bean

finishBeanFactoryInitialization最重要的功能是实例化所有非延迟加载的bean:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 初始化ConversionService的实例化
    // 然后赋值给beanFactory.conversionService实例
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    // Register a default embedded value resolver if no BeanFactoryPostProcessor
    // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    // 如果beanFactory中没有@Value解析器
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // 类加载期间织入的切面 Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // 停止使用临时ClassLoader Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    // 冻结配置,不再允许改变 Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();
    // 实例化所有非延迟加载的bean Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

2.12  完成刷新

protected void finishRefresh() {
    // 清理资源缓存 Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();
    // 初始化LifecycleProcessor 生命周期处理器用于在启动或结束的时候处理Bean Initialize lifecycle processor for this context.
    initLifecycleProcessor();
    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();
    // 发布ContextRefreshedEvent Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));
    // Participate in LiveBeansView MBean, if active.
    // 如果配置了"spring.liveBeansView.mbeanDomain"的系统属性,指定了MBeanServer,
    // 那么会将ApplicationContext注册到MBeanServer中,
    // 可以通过MBeanServer,对spring容器中的bean,进行实时的查看和管理
    if (!NativeDetector.inNativeImage()) {
        LiveBeansView.registerApplicationContext(this);
    }
}

2.13  注册关闭钩子

最后刷新下上文后会注册应用关闭钩子,应用关闭时,钩子会开启线程去执行一些关闭和释放资源的任务:

// ###SpringApplication
private void refreshContext(ConfigurableApplicationContext context) {
    // 上下文的刷新
    refresh(context);
    // 注册关闭钩子
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}
public void registerShutdownHook() {
    if (this.shutdownHook == null) {
        // No shutdown hook registered yet.
        this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
            @Override
            public void run() {
                synchronized (startupShutdownMonitor) {
                    // 调用关闭方法
                    doClose();
                }
            }
        };
        // 在JVM中增加一个关闭的钩子,将SpringApplicationShutdownHook 放进去
        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    }
}

那我们简单看下doClose方法:

@SuppressWarnings("deprecation")
protected void doClose() {
    // Check whether an actual close attempt is necessary...
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Closing " + this);
        }
        if (!NativeDetector.inNativeImage()) {
            LiveBeansView.unregisterApplicationContext(this);
        }
        try {
            // 发布关闭事件 Publish shutdown event.
            publishEvent(new ContextClosedEvent(this));
        }
        catch (Throwable ex) {
            logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
        }
        // Stop all Lifecycle beans, to avoid delays during individual destruction.
        if (this.lifecycleProcessor != null) {
            try {
                this.lifecycleProcessor.onClose();
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
            }
        }
        // 销毁bean Destroy all cached singletons in the context's BeanFactory.
        destroyBeans();
        // 关闭bean工厂 Close the state of this context itself.
        closeBeanFactory();
        // 这里SpringBoot 用于关闭web容器比如停止掉 tomcat Let subclasses do some final clean-up if they wish...
        onClose();
        // Reset local application listeners to pre-refresh state.
        if (this.earlyApplicationListeners != null) {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }
        // Switch to inactive.
        this.active.set(false);
    }
}

3  小结

好了,关于刷新上下文的我们就看到这里,细节其实还很多很多,我们也只是看了冰山一角哈,还需要我们再多看多琢磨的,有理解不对的地方欢迎指正哈。

posted @ 2023-05-06 17:37  酷酷-  阅读(295)  评论(0编辑  收藏  举报