spring擴展啓動流程-refresh

spring擴展啓動流程-refresh

XmlWebApplicationContext

spring-webmvc啓動流程中,咱們在對wac的刷新過程並無詳細的解釋,只是一筆帶過。java

無論是從ContextLoaderListener進入的,仍是Servlet的init方法進入的,都離不開spring總體的初始化。僅僅有bean的讀取,加載的spring是不完整的,spring還須要這些擴展的部分,讓spring更完善,先來看看入口吧。web

// ContextLoader.java
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
	//...
	wac.refresh();
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
		//...
		wac.refresh();
}

refresh

refresh函數中幾乎包含了ApplicationContext提供的全部功能,並且此函數中的邏輯很清楚,瞅一下吧。spring

調試能夠直接從ClassPathXmlApplicationContext這個類駛入,構造方法直接就能駛入這個方法,並初始化完成整個環境。緩存

// AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      // 準備刷新的上下文環境
      prepareRefresh();
       
      // Tell the subclass to refresh the internal bean factory.
      // 初始化BeanFactory,並進行xml文件讀取
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
       
      // Prepare the bean factory for use in this context.
      // 對BeanFactory進行各類功能填充
      prepareBeanFactory(beanFactory);
      try {
         // Allows post-processing of the bean factory in context subclasses.
         // 子類覆蓋作額外的處理
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         // 激活各類BeanFactory處理器
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         // 註冊攔截Bean建立的Bean處理器,這裏只是註冊,調用是在getBean的時候
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         // 爲上下文初始化Message源,即不一樣語言的消息體,國際化處理
         initMessageSource();

         // Initialize event multicaster for this context.
         // 初始化應用消息廣播器,並放入"ApplicationEventMulticaster" Bean中 
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 留給子類來初始化其餘的Bean
         onRefresh();

         // Check for listener beans and register them.
         // 在全部註冊的Bean中查找Listenter bean,註冊到消息廣播器中
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //初始化剩下的單例(非惰性)
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 完成刷新過程,通知生命週期處理器lifecycleProcessor完成刷新過程,同時發出ContextRefreshEvent通知別人
         finishRefresh();
      }
      catch (BeansException ex) {
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }
   }
}

prepareRefresh

//AbstractApplicationContext.java
protected void prepareRefresh() {
    //...
    //留給子類覆蓋
    initPropertySources();
    //屬性文件驗證,確保須要的文件都已經放入環境中
    getEnvironment().validateRequiredProperties();
    //...
}

obtainFreshBeanFactory

初始化BeanFactory,對xml文件的讀取,就是從這個地方開始的,使用的是默認的DefaultListableBeanFactory。mvc

//AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //初始化BeanFactory
	refreshBeanFactory();
    //返回初始化以後的BeanFactory
	return getBeanFactory();
}
//AbstractRefreshableApplicationContext.java
protected final void refreshBeanFactory() throws BeansException {
    //檢查是否已經有了初始化的BeanFactory
    if (hasBeanFactory()) {
        //銷燬全部的bean
        destroyBeans();
        //關閉並銷燬BeanFactory
        closeBeanFactory();
    }
    try {
        //建立默認的DefaultListableBeanFactory,子類能夠覆蓋該方法
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        //定製BeanFactory,包括是否容許覆蓋同名稱的不一樣定義的對象以及循環依賴
        customizeBeanFactory(beanFactory);
        //初始化XmlBeanDefinitionReader,並進行xml文件的解析。
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {...}
}

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    //設置是否容許同名不一樣定義的bean覆蓋
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    //設置是否容許循環依賴
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

prepareBeanFactory

至此,spring已經完成了對配置的解析,ApplicationContext在功能上的擴展也由此開始。app

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    beanFactory.setBeanClassLoader(getClassLoader());
    //設置表達式語言處理器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //設置一個默認的屬性解析器PropertyEditor
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    //添加BeanPostProcessor
    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);

    //註冊依賴解析,也是spring的bean,可是會特殊一些,下邊會有解釋
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    //添加BeanPostProcessor
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //增長對AspectJ的支持
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    //添加默認的系統環境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());
    }
}
主要擴展:
1. 增長對SPEL語言的支持;
2. 增長對屬性編輯器的支持,這些PropertyEditors在這裏只是註冊,使用的時候是將bean包裝成BeanWrapper,包裝後的BeanWrapper的就包含了全部的這些PropertyEditors,以便後期給bean設置屬性的時候使用;
3. 增長對一些內置類(實際上就是前置處理器),好比Aware接口的信息注入;
4. 設置依賴功能可忽略的接口;
5. 註冊一些固定的bean,這些都是特殊的依賴解析,好比當註冊了BeanFactory.class的依賴解析以後,當bean的屬性注入的時候,一旦檢測到屬性爲BeanFactory類型便會將beanFactory的實例注入進去;
6. 增長對AspectJ的支持;
7. 將相關環境變量及屬性以單例模式註冊。

invokeBeanFactoryPostProcessors

激活註冊的BeanFactoryPostProcessor。這個接口跟BeanPostProcessor相似,能夠對bean的定義(配置元數據)進行處理,做用範圍是容器級的,只對本身的容器的bean進行處理。典型應用PropertyPlaceholderConfigurer。編輯器

這部分代碼有點長,不貼了,本身去看吧。函數

registerBeanPostProcessors

註冊全部的bean先後置處理器BeanPostProcessor,這裏只是註冊,調用是在bean建立的時候。post

代碼也有點長,不貼了,本身去看吧~~ui

initMessageSource

國際化處理,若是想使用自定義的,bean name是指定了的MESSAGE_SOURCE_BEAN_NAME = "messageSource"。

protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //根據指定的名稱查找messageSource,若是容器中註冊了指定名稱的messageSource,就使用註冊的
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        //...日誌
    }
    else {
        //容器中沒有註冊指定名稱的messageSource,使用默認的DelegatingMessageSource
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        //...日誌
    }
}

initApplicationEventMulticaster

初始化應用的事件廣播器,用於事件監聽,邏輯跟初始化國際化MessageSource是同樣的,也是有一個特定的名稱。若是beanFactory有就是用註冊的,若是沒有就是用默認的SimpleApplicationEventMulticaster。

應用中的listener都是註冊到這個廣播器,由廣播器統一廣播的。

registerListeners

在全部註冊的Bean中查找Listenter bean,註冊到消息廣播器中。

protected void registerListeners() {
    // 首先註冊靜態註冊的監聽器(代碼註冊的)
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 獲取容器中全部配置的listener並註冊
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 對earlyApplicationEvents這些事件進行廣播,實際上就是遍歷全部的listener,找到能夠處理event的listener處理
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

finishBeanFactoryInitialization

初始化剩下的非惰性單例,若是某個單例依賴了惰性的單例,那麼這個惰性的單例也會被初始化,這個很好理解吧。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化ConversionService,跟PropertyEditor相似
    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));
    }

    //則註冊默認的嵌入值解析器
    //例如PropertyPlaceholderConfigurer bean)以前註冊過:
    //主要用於註解屬性值的解析。
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    //單例bean初始化以前首先初始化LoadTimeWeaverAware,以支持aop,AspectJ
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    beanFactory.setTempClassLoader(null);

    //凍結bean定義(BeanDefinition),表示全部的bean定義進不被修改或進行進一步處理
    beanFactory.freezeConfiguration();

    //初始化非惰性單例,實際上就是遍歷全部的beanName,而後一一調用getBean()
    beanFactory.preInstantiateSingletons();
}

finishRefresh

protected void finishRefresh() {
    //清除上下文級別(context-level)的資源緩存,好比由scanning產生的ASM元數據
    clearResourceCaches();

    //初始化LifecycleProcessor
    initLifecycleProcessor();

    //使用LifecycleProcessor來啓動Lifecycle子類
    getLifecycleProcessor().onRefresh();

    //上下文刷新完成,發佈事件
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

初始化LifecycleProcessor的時候,跟初始化MessageResource同樣,沒有自定義的就是用默認的DefaultLifecycleProcessor。

getLifecycleProcessor().onRefresh()會使用咱們註冊的LyfecycleProcessor來啓動咱們註冊的SmartLifeCycle的子類。看一下代碼吧。

//默認的DefaultLifecycleProcessor.java
public void onRefresh() {
    startBeans(true);
    this.running = true;
}

private void startBeans(boolean autoStartupOnly) {
    //獲取全部的LifeCycle類型的bean
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    Map<Integer, LifecycleGroup> phases = new HashMap<>();
    lifecycleBeans.forEach((beanName, bean) -> {
        //默認的DefaultLifecycleProcessor只會啓動SmartLifecycle的,或者非自動啓動的類型
        //SmartLifecycle繼承了Phases接口
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean);
            LifecycleGroup group = phases.get(phase);
            if (group == null) {
                group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                //添加到須要啓動的集合中
                phases.put(phase, group);
            }
            group.add(beanName, bean);
        }
    });
    //啓動須要啓動的這些LifeCycle
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<>(phases.keySet());
        Collections.sort(keys);
        for (Integer key : keys) {
            phases.get(key).start();
        }
    }
}

over ...

相關文章
相關標籤/搜索