『深刻學習 Spring Boot』——refresh 方法

 80ae165dbfb9c81ebcf6fd5b548f6bfc.jpeg

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) 方法體中:web

// 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

方法註釋:準備此上下文以進行刷新,設置其啓動日期和活動標誌以及執行屬性源的任何初始化。session

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的各類屬性。app

方法註釋:配置工廠的標準上下文特徵,例如上下文的ClassLoader和後處理器ide

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());
        }
    }

此方法,作了如下幾件事:post

  • 設置 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 的整體流程。對於一些細節,留待之後慢慢學習,一口又吃不成個大胖子。

最後

最近我整理了整套《JAVA核心知識點總結》,說實話 ,做爲一名Java程序員,不論你需不須要面試都應該好好看下這份資料。拿到手老是不虧的~個人很多粉絲也所以拿到騰訊字節快手等公司的Offer

Java進階之路羣,找管理員獲取哦-!

564cfb6a63a8758235e809086a455a27.png

c3947289faba06d941eed1f88835dc36.png

相關文章
相關標籤/搜索