『深入学习 Spring Boot』(七) refresh 方法

668 阅读6分钟

前言

这一节,我们来看一下 Spring 启动的核心方法 -- refresh 方法。

refresh 方法,是 Spring Bean 配置读取加载入口,也是 Spring 框架的启动流程。

refresh 方法

refresh 方法概览

我们还是从 SpringApplication.run(String... args) 看起。

// SpringApplication # run(String... args) # 311-313
public ConfigurableApplicationContext run(String... args) {
      // …………
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            refreshContext(context);
            afterRefresh(context, applicationArguments);
      // …………
        return context;
    }

我们进入 refreshContext(context) 方法体中:

// SpringApplication # refreshContext(ConfigurableApplicationContext context) # 390
private void refreshContext(ConfigurableApplicationContext context) {
        refresh(context);
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            }
            catch (AccessControlException ex) {
                // Not allowed in some environments.
            }
        }
    }

很显然,核心方法还是去调用了 refresh(context):

    // SpringApplication # refresh(ApplicationContext applicationContext) # 742
protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext) applicationContext).refresh();
    }

继续进入((AbstractApplicationContext) applicationContext).refresh()

// AbstractApplicationContext # refresh() # 515
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
      // 为刷新容器,准备上下文
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
      // 告诉子类刷新内部bean工厂
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the bean factory for use in this context.
      // 准备在此上下文使用的bean工厂。
            prepareBeanFactory(beanFactory);
            try {
              // Allows post-processing of the bean factory in context subclasses.
        // 允许在上下文子类中对bean工厂进行后处理
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
         // 调用在上下文中注册为bean的工厂处理器。
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
         // 注册拦截Bean创建的Bean处理器。
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
        // 初始化此上下文的消息源。
                initMessageSource();
                // Initialize event multicaster for this context.
        // 为上下文,初始化事件广播器
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
        // 在特定上下文子类中初始化其他特殊bean。
                onRefresh();
                // Check for listener beans and register them.
        // 检查监听器并注册。
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
         // 实例化所有剩余的(非延迟初始化)单例。
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
        // 发布相应的事件。
                finishRefresh();
            }
      // …………
    }

prepareRefresh

方法注释:准备此上下文以进行刷新,设置其启动日期和活动标志以及执行属性源的任何初始化。

protected void prepareRefresh() {
        // 设置启动日期、活动标志
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
    // …………
        // Initialize any placeholder property sources in the context environment.
         // 初始化属性设置
        initPropertySources();
 
        // Validate that all properties marked as required are resolvable:
        // see ConfigurablePropertyResolver#setRequiredProperties
      // 验证必备属性
        getEnvironment().validateRequiredProperties();
 
        // Store pre-refresh ApplicationListeners...
    // 保存刷新前的监听器
        if (this.earlyApplicationListeners == null) {
            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<>();
    }

obtainFreshBeanFactory

// AbstractApplicationContext # obtainFreshBeanFactory() # 635
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }

这个方法比较简单,做了两件事:

  • 设置 beanFactory 的序列化 id
  • 获取 beanFacotory

prepareBeanFactory

此方法,主要设置 从obtainFreshBeanFactory()获取到的 beanFacotory的各种属性。

方法注释:配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
    // 告诉内部bean工厂使用上下文的类加载器等。
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
 
        // Configure the bean factory with context callbacks.
    // 使用上下文回调配置Bean工厂。
        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 interface not registered as resolvable type in a plain factory.
    // BeanFactory接口未在普通工厂中注册为可解析类型。
        // MessageSource registered (and found for autowiring) as a bean.
    // MessageSource注册为Bean(并发现用于自动装配)。
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
 
        // Register early post-processor for detecting inner beans as ApplicationListeners.
    // 注册早期的后处理器以将内部bean检测为ApplicationListeners。
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
 
        // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 检测LoadTimeWeaver,并准备进行织入(如果找到)。
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
      // 设置一个临时的ClassLoader以进行类型匹配。
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
 
        // Register default environment beans.
    // 注册默认环境Bean。
        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());
        }
    }

此方法,做了以下几件事:

  • 设置 beanFactory 的一些属性
  • 添加后置处理器
  • 设置忽略的自动装配接口
  • 注册一些组件

postProcessBeanFactory(beanFactory)

这里是一个空实现,留给子类重写。可以在 beanFactory 完成创建后做进一步设置。

对于 Servlet 而言,就是设置一些作用域之类的,例如 request、session 等。

invokeBeanFactoryPostProcessors(beanFactory)

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
 
        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

这里的主要逻辑在 invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())

这个方法体太长了,就不贴出来了。主要做了两件事:

  • 调用BeanDefinitionRegistryPostProcessor实现向容器内添加bean的定义。

    其实这里我们在上一小节实践过了,下面就是我们添加的 Bean 。

    @Componentpublic class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();        rootBeanDefinition.setBeanClass(MyTwoBean.class);        beanDefinitionRegistry.registerBeanDefinition("myTwoBean",rootBeanDefinition);    }    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {     }}
    
  • 调用BeanFactoryPostProcessor实现向容器内添加bean的定义添加属性。

registerBeanPostProcessors(beanFactory)

这个方法和invokeBeanFactoryPostProcessors(beanFactory)是类似的。

找到BeanPostPocessor的实现,排序后注册进容器内。

initMessageSource()

主要是国际化、多语言配置。

不是重点,略过。

initApplicationEventMulticaster()

初始化事件广播器。监听器相关内容,我们之前已经学习过。此处也是类似的。

// 当前有监听器就用监听器;没有的话,就新建一个。protected void initApplicationEventMulticaster() {        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {            this.applicationEventMulticaster =                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);        }        else {            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);        }    }

onRefresh()

子类实现。Servlet 下主要表现为创建 web 容器。

// ServletWebServerApplicationContext # onRefresh() # 150protected void onRefresh() {        super.onRefresh();        try {            createWebServer();        }        catch (Throwable ex) {            throw new ApplicationContextException("Unable to start web server", ex);        }    }

我们知道super.onRefresh()是空实现,所以直接看createWebServer()

// 这个方法就是:创建容器的方法。我们暂不深究。private void createWebServer() {        WebServer webServer = this.webServer;        ServletContext servletContext = getServletContext();        if (webServer == null && servletContext == null) {            ServletWebServerFactory factory = getWebServerFactory();            this.webServer = factory.getWebServer(getSelfInitializer());        }        else if (servletContext != null) {            try {                getSelfInitializer().onStartup(servletContext);            }            catch (ServletException ex) {                throw new ApplicationContextException("Cannot initialize servlet context", ex);            }        }        initPropertySources();    }

registerListeners()

    protected void registerListeners() {        // Register statically specified listeners first.    // 首先注册静态指定的侦听器。        for (ApplicationListener<?> listener : getApplicationListeners()) {            getApplicationEventMulticaster().addApplicationListener(listener);        }     // 把容器中 listenerBean 注册        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...    // 当Bean没加载完时,事件是发布不出去的,所以暂时保存在earlyApplicationEvents中    // 到此时,再把攒下的事件发布出去。        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;        this.earlyApplicationEvents = null;        if (earlyEventsToProcess != null) {            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {                getApplicationEventMulticaster().multicastEvent(earlyEvent);            }        }    }

finishBeanFactoryInitialization(beanFactory)

实例化BeanFactory 中已经被注册但是没被实例化的所有实例。

这是比较重要的 Bean 实例化流程。所以我们后面单开一节来学习。

所以,暂时不过多探究源码了。

finishRefresh()

protected void finishRefresh() {    // Clear context-level resource caches (such as ASM metadata from scanning).  // 清除资源缓存    clearResourceCaches();     // Initialize lifecycle processor for this context.  // 初始化生命周期处理器(非学习重点)    initLifecycleProcessor();     // Propagate refresh to lifecycle processor first.  // 生命周期处理器的 onRefresh() ,也是非学习重点。    getLifecycleProcessor().onRefresh();     // Publish the final event.  // 发布容器已刷新事件    publishEvent(new ContextRefreshedEvent(this));     // Participate in LiveBeansView MBean, if active.  // 非学习重点。    LiveBeansView.registerApplicationContext(this);}

resetCommonCaches()

此方法在 finally {} 中被调用,做一些清除缓存的工作。

    protected void resetCommonCaches() {        ReflectionUtils.clearCache();        AnnotationUtils.clearCache();        ResolvableType.clearCache();        CachedIntrospectionResults.clearClassLoader(getClassLoader());    }

总结

至此,refresh 方法我们已经过了一遍。

这一小节,还是着重于 refresh 的总体流程。对于一些细节,留待以后慢慢学习,一口又吃不成个大胖子。