Spring IOC-基於XML配置的容器

Spring IOC-基於XML配置的容器

咱們先分析一下AbstractXmlApplicationContext這個容器的加載過程。前端

AbstractXmlApplicationContext的老爸是AbstractRefreshableApplicationContextjava

它老爸是AbstractApplicationContext的兩個兒子之一。web

1. 開始

從一張關係圖開始:spring

demo中使用了ClassPathXmlApplicationContext,而後還有它旁邊的兄弟FileSystemXmlApplicationContext,它們倆都是從xml配置文件加載配置的後端

除了這兩個以外還有一個AnnotationConfigApplicationContext數組

2. 源碼分析

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
  //配置文件數組
  private Resource[] configResources;

  // 指定ApplicationContext的父容器
  public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
  }
  
  public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
  		this(new String[] {configLocation}, true, null);
  }
  
  public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
  		this(configLocations, true, null);
  }
  
  public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent) throws BeansException {
  
  		this(configLocations, true, parent);
  }
  
  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {

    super(parent);
    // 根據提供的路徑,處理成配置文件數組(以分號、逗號、空格、tab、換行符分割)
    setConfigLocations(configLocations);
    
    if (refresh) {
      refresh();
    }
  }
}
複製代碼

能夠看到,ClassPathXmlApplicationContext提供了一系列的構造方法,主要是爲了指定配置文件的位置,以及設置一個父容器,還有就是調用了refresh()方法, setConfigLocations()這個很簡單,看來主要的就是在refresh方法中了緩存

setConfigLocations()

先看看setConfigLocations()方法中作了什麼websocket

public void setConfigLocations(String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            //往下看
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

protected String resolvePath(String path) {
    return getEnironment().resolveRequiredPlaceholders(path);
}
複製代碼

setConfigLocations()方法的主要工做有兩個:建立環境對象ConfigurableEnvironment和處理構造ClassPathXmlApplicationContext時傳入的字符串中的佔位符, 這裏getEnvironment()就涉及到了建立環境變量相關的操做了session

getEnvironment()獲取環境變量多線程

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}
複製代碼

在上面的getEnvironment()方法的返回值中,咱們看到一個ConfigurableEnvironment的類 先看看這個類的結構:

這個接口比較重要的就是兩部份內容了,一個是設置Spring的環境就是咱們常常用的spring.profile配置。另外就是系統資源Property

接着看看getEnvironment()中的createEnvironment()方法, 這個類建立了一個StandardEnvironment:

public class StandardEnvironment extends AbstractEnvironment {

	/** System environment property source name: {@value} 系統屬性 eg:System.getProperty("java.home"); */
	public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

	/** JVM system properties property source name: {@value} JVM 屬性 --name=ranger OR -Dname=ranger */
	public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";


	/** * Customize the set of property sources with those appropriate for any standard * Java environment: * 使用任何適合標準Java環境來定義資源集 * <ul> * <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} * <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME} * </ul> * JVM屬性的優先級比系統屬性高 * <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will * take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}. * @see AbstractEnvironment#customizePropertySources(MutablePropertySources) * 根據父類中對於這個方法的解釋: 子類能夠重寫這個方法來添加自定義的PropertySource, 添加方式以下: public class Level1Environment extends AbstractEnvironment { &#064;Override protected void customizePropertySources(MutablePropertySources propertySources) { super.customizePropertySources(propertySources); // no-op from base class propertySources.addLast(new PropertySourceA(...)); propertySources.addLast(new PropertySourceB(...)); } } 在Level1Environment的子類中,還能夠這樣添加自定義的PropertySource,並且加入的這個是有優先級的, 好比上面的示例中, 子類添加的 > A > B * @see #getSystemProperties() * @see #getSystemEnvironment() */
	@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

}
複製代碼

而這個類中的customizePropertySources方法就會往資源列表中添加Java進程中的變量和系統的環境變量。 能夠看出一個Environment便是包含了一系列PropertySource的資源集合, 而PropertySource就是資源屬性

再次回到resolvePath()方法,一直跟蹤這個方法,最後到了org.springframework.util.PropertyPlaceholderHelper.parseStringValue()方法,這個方法主要就是處理全部使用${}方式的佔位符

protected String parseStringValue( String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

      StringBuilder result = new StringBuilder(value);
      int startIndex = value.indexOf(this.placeholderPrefix);
      while (startIndex != -1) {
         int endIndex = findPlaceholderEndIndex(result, startIndex);
         if (endIndex != -1) {
            String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
            String originalPlaceholder = placeholder;
            if (!visitedPlaceholders.add(originalPlaceholder)) {
               throw new IllegalArgumentException(
                     "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
            }
            placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
            // Now obtain the value for the fully resolved key...
            String propVal = placeholderResolver.resolvePlaceholder(placeholder);
            if (propVal == null && this.valueSeparator != null) {
               int separatorIndex = placeholder.indexOf(this.valueSeparator);
               if (separatorIndex != -1) {
                  String actualPlaceholder = placeholder.substring(0, separatorIndex);
                  String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                  propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                  if (propVal == null) {
                     propVal = defaultValue;
                  }
               }
            }
            if (propVal != null) {
               // Recursive invocation, parsing placeholders contained in the
               // previously resolved placeholder value.
               propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
               result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
               if (logger.isTraceEnabled()) {
                  logger.trace("Resolved placeholder '" + placeholder + "'");
               }
               startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
            }
            else if (this.ignoreUnresolvablePlaceholders) {
               // Proceed with unprocessed value.
               startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
            }
            else {
               throw new IllegalArgumentException("Could not resolve placeholder '" +
                     placeholder + "'" + " in value \"" + value + "\"");
            }
            visitedPlaceholders.remove(originalPlaceholder);
         }
         else {
            startIndex = -1;
         }
      }

      return result.toString();
   }
複製代碼

關於PropertyResolver之後再作解析

refresh()

這個方法很長,將會長篇幅來介紹,先看個大概幹了什麼:

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

複製代碼

接下來逐步解剖:

  1. synchronized 爲了不多線程環境下容器還沒啓動完畢,再次啓動引發的衝突
  2. prepareRefresh() 這個方法作一些準備工做,記錄容器的啓動時間,標記以啓動狀態等
protected void prepareRefresh() {
      this.startupDate = System.currentTimeMillis();
      this.closed.set(false);
      this.active.set(true);

      if (logger.isInfoEnabled()) {
         logger.info("Refreshing " + this);
      }

      // 初始化加載配置文件方法,並無具體實現,一個留給用戶的擴展點
      initPropertySources();

      // 檢查環境變量
      getEnvironment().validateRequiredProperties();

      this.earlyApplicationEvents = new LinkedHashSet<>();
   }
複製代碼

其中有個方法爲validateRequiredProperties(),這個方法是爲了檢查全部須要的環境變量是否爲空,若是爲空就中止啓動,而後拋出異常

  1. obtainFreshBeanFactory() 這個方法負責了BeanFactory的初始化、Bean的加載和註冊等事件
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 核心
   refreshBeanFactory();

   // 返回建立的 BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}
複製代碼
  • refreshBeanFactory():
/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 判斷當前ApplicationContext是否存在BeanFactory,若是存在的話就銷燬全部 Bean,關閉 BeanFactory
    // 注意,一個應用能夠存在多個BeanFactory,這裏判斷的是當前ApplicationContext是否存在BeanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
         // 初始化DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        // 設置 BeanFactory 的兩個配置屬性:是否容許 Bean 覆蓋、是否容許循環引用
        customizeBeanFactory(beanFactory);
        // 加載 Bean 到 BeanFactory 中
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}
複製代碼

在這裏初始化了一個DefaultListableBeanFactory,看看這個類的繼承圖

這是一個很是龐大的傢伙

  • loadBeanDefinitions()

先了解BeanDefinition,咱們知道BeanFactory是一個Bean容器,而BeanDefinition就是Bean的一種形式(它裏面包含了Bean指向的類、是否單例、是否懶加載、Bean的依賴關係等相關的屬性)。BeanFactory中就是保存的BeanDefinition

BeanDefinition的接口定義:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

   // Bean的生命週期,默認只提供sington和prototype兩種,在WebApplicationContext中還會有request, session, globalSession, application, websocket 等
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

  
   // 設置父Bean
   void setParentName(String parentName);

   // 獲取父Bean
   String getParentName();

   // 設置Bean的類名稱
   void setBeanClassName(String beanClassName);

   // 獲取Bean的類名稱
   String getBeanClassName();


   // 設置bean的scope
   void setScope(String scope);

   String getScope();

   // 設置是否懶加載
   void setLazyInit(boolean lazyInit);

   boolean isLazyInit();

   // 設置該Bean依賴的全部Bean
   void setDependsOn(String... dependsOn);

   // 返回該Bean的全部依賴
   String[] getDependsOn();

   // 設置該Bean是否能夠注入到其餘Bean中
   void setAutowireCandidate(boolean autowireCandidate);

   // 該Bean是否能夠注入到其餘Bean中
   boolean isAutowireCandidate();

   // 同一接口的多個實現,若是不指定名字的話,Spring會優先選擇設置primary爲true的bean
   void setPrimary(boolean primary);

   // 是不是primary的
   boolean isPrimary();

   // 指定工廠名稱
   void setFactoryBeanName(String factoryBeanName);
   // 獲取工廠名稱
   String getFactoryBeanName();
   // 指定工廠類中的工廠方法名稱
   void setFactoryMethodName(String factoryMethodName);
   // 獲取工廠類中的工廠方法名稱
   String getFactoryMethodName();

   // 構造器參數
   ConstructorArgumentValues getConstructorArgumentValues();

   // Bean 中的屬性值,後面給 bean 注入屬性值的時候會說到
   MutablePropertyValues getPropertyValues();

   // 是否 singleton
   boolean isSingleton();

   // 是否 prototype
   boolean isPrototype();

   // 若是這個 Bean 是被設置爲 abstract,那麼不能實例化,經常使用於做爲 父bean 用於繼承
   boolean isAbstract();

   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}
複製代碼

loadBeanDefinitions()方法會讀取配置文件加載各個BeanDefinition,而後放到BeanFactory

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // 實例化XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // 初始化 BeanDefinitionReader
   initBeanDefinitionReader(beanDefinitionReader);
   // 接着往下看
   loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}
複製代碼

而後調用XmlBeanDefinitionReaderloadBeanDefinitions()方法

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
   Assert.notNull(resources, "Resource array must not be null");
   int counter = 0;
   // 循環,處理全部配置文件,我們這裏就傳了一個
   for (Resource resource : resources) {
      // 繼續往下看
      counter += loadBeanDefinitions(resource);
   }
   // 最後返回加載的全部BeanDefinition的數量
   return counter;
}

@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
  return loadBeanDefinitions(location, null);
}


public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
  ResourceLoader resourceLoader = getResourceLoader();
  if (resourceLoader == null) {
     throw new BeanDefinitionStoreException(
           "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
  }

  if (resourceLoader instanceof ResourcePatternResolver) {
     try {
       //將配置文件轉換爲Resource對象
        Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
       //接着往下看
        int loadCount = loadBeanDefinitions(resources);
        if (actualResources != null) {
           for (Resource resource : resources) {
              actualResources.add(resource);
           }
        }
        if (logger.isDebugEnabled()) {
           logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
        }
        return loadCount;
     }
     catch (IOException ex) {
        throw new BeanDefinitionStoreException(
              "Could not resolve bean definition resource pattern [" + location + "]", ex);
     }
  }
  else {
     // Can only load single resources by absolute URL.
     Resource resource = resourceLoader.getResource(location);
     int loadCount = loadBeanDefinitions(resource);
     if (actualResources != null) {
        actualResources.add(resource);
     }
     if (logger.isDebugEnabled()) {
        logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
     }
     return loadCount;
  }
}
複製代碼

這裏面屢次提到了一個XmlBeanDefinitionReader,這個類主要實現的接口是BeanDefinitionReader

這個類如何讀取配置文件,建立BeanDefinition,而後註冊到容器beanDefinitionMap,咱們之後再來細講,看太遠就回不來了

  1. prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)

如今回到refresh()方法的主線上,如今refresh已經走到了prepareBeanFactory,看名字就知道是給BeanFactory準備一些東西, 實際上這個方法就是BeanFactory的類加載器,添加BeanPostProcessor,而後手動註冊幾個特殊的bean

/** * Configure the factory's standard context characteristics, * such as the context's ClassLoader and post-processors. * @param beanFactory the BeanFactory to configure */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    // 設置當前BeanFacoty的類加載器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 設置BeanExpressionResolver
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 註冊PropertyEditor
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    // 在全部實現了Aware接口的bean在初始化的時候,這個 processor負責回調
    // 例如,bean獲取ApplicationContext 而 implement ApplicationContextAware
    // 固然,它也處理實現了 EnvironmentAware、ResourceLoaderAware 等的bean
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    // 下面幾行的意思就是,若是某個 bean 依賴於如下幾個接口的實現類的bean,在自動裝配的時候忽略它們
    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.
    // MessageSource registered (and found for autowiring) as a bean.
    // 下面幾行就是爲特殊的幾個 bean 賦值,若是有 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.
    // 註冊 事件監聽器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 若是存在bean名稱爲loadTimeWeaver的bean則註冊一個BeanPostProcessor
    // 具體的這個LoadTimeWeaver是幹啥的後面再說
    if (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()));
    }

    // Register default environment beans.
    // 註冊environment這個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());
    }
    // JVM屬性
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}
複製代碼
  1. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

這裏是Spring中提供的一個擴展,調用類中的,這個留給子類去擴展,具體的子類能夠在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現類或作點什麼事.方法定義以下

/** * Modify the application context's internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for registering special * BeanPostProcessors etc in certain ApplicationContext implementations. * @param beanFactory the bean factory used by the application context */
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

複製代碼
  1. invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)

這裏是Spring中提供的一個擴展,如有bean實現了BeanFactoryPostProcessor,那麼在容器初始化之後,Spring 會負責調用裏面的 postProcessBeanFactory 方法 這個接口的定義以下:

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanfactory) throws BeansException;
}
複製代碼
  1. registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory);

這裏又是一個擴展點,註冊攔截bean建立的bean處理器,每一個bean建立的時候都會調用全部的BeanPostProcessor 註冊 BeanPostProcessor 的實現類,注意不是BeanFactoryPostProcessor 此接口有兩個方法: postProcessBeforeInitializationpostProcessAfterInitialization分別會在Bean初始化以前和初始化以後獲得執行

  1. initMessageSource()

初始化當前 ApplicationContextMessageSource,爲了國際化

  1. initApplicationEventMulticaster()

初始化當前BeanFactory事件廣播器,會註冊一個SimpleApplicationEventMulticaster單例,能夠調用ApplicationEventMulticastermulticastEvent方法來觸發一個事件, ApplicationEventMulticaster會調用相應的ApplicationListener,到後面講Spring事件機制再細說

  1. onRefresh()

這裏又是給子類的一個擴展點,

/** * Template method which can be overridden to add context-specific refresh work. * Called on initialization of special beans, before instantiation of singletons. * <p>This implementation is empty. * @throws BeansException in case of errors * @see #refresh() */
protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}
複製代碼
  1. registerListeners();

檢測Listener而後註冊到容器

protected void registerListeners() {
  //先添加手動set的一些監聽器
  for (ApplicationListener<?> listener : getApplicationListeners()) {
     getApplicationEventMulticaster().addApplicationListener(listener);
  }

  //取到監聽器的名稱,設置到廣播器
  String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
  for (String listenerBeanName : listenerBeanNames) {
     getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  }

  // 若是存在早期應用事件,發佈
  Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  this.earlyApplicationEvents = null;
  if (earlyEventsToProcess != null) {
     for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
     }
  }
}

複製代碼
  1. finishBeanFactoryInitialization()

在前面refresh方法內走了那麼長的路,可是依然沒有完成bean的初始化和依賴注入,到這裏,Spring以爲時機成熟了,就開始初始化不是懶加載的單例bean

這裏又會迎來一段艱難的路程

/** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 爲當前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 bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    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);
    }

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons. 
    beanFactory.preInstantiateSingletons();
}

複製代碼
  • ConversionService 這個是類型轉換相關的類,場景之一就是將前端傳過來的參數和後端的controller方法上的參數格式轉換的時候使用

  • EmbeddedValueResolver 利用EmbeddedValueResolver能夠很方便的實現讀取配置文件的屬性

@Component
public class PropertiesUtil implements EmbeddedValueResolverAware {

    private StringValueResolver resolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }


    /** * 獲取屬性時直接傳入屬性名稱便可 */
    public String getPropertiesValue(String key) {
        StringBuilder name = new StringBuilder("${").append(key).append("}");
        return resolver.resolveStringValue(name.toString());
    }

}

複製代碼
  • beanFactory.preInstantiateSingletons()

這個方法是重點

public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }
   // this.beanDefinitionNames 保存了全部的 beanNames
   List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

   for (String beanName : beanNames) {
      // Return a merged RootBeanDefinition, traversing the parent bean definition,if the specified bean corresponds to a child bean definition.
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

      // 不是抽象類、是單例的且不是懶加載的
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // 處理 FactoryBean
         if (isFactoryBean(beanName)) {
            //在 beanName 前面加上「&」 符號
            final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            // 判斷當前 FactoryBean 是不是 SmartFactoryBean 的實現
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
               isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                  @Override
                  public Boolean run() {
                     return ((SmartFactoryBean<?>) factory).isEagerInit();
                  }
               }, getAccessControlContext());
            }
            else {
               isEagerInit = (factory instanceof SmartFactoryBean &&
                     ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            if (isEagerInit) {

               getBean(beanName);
            }
         }
         else {
            // 不是FactoryBean的直接使用此方法進行初始化
            getBean(beanName);
         }
      }
   }


  
   // 若是bean實現了 SmartInitializingSingleton 接口的,那麼在這裏獲得回調
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
               @Override
               public Object run() {
                  smartSingleton.afterSingletonsInstantiated();
                  return null;
               }
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

複製代碼

能夠看到,不管是不是FactoryBean,最後都會調用getBean(String beanName)方法

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
   // 獲取beanName,處理兩種狀況,一個是前面說的 FactoryBean(前面帶 ‘&’),再一個這個方法是能夠根據別名來獲取Bean的,因此在這裏是要轉換成最正統的BeanName
  //主要邏輯就是若是是FactoryBean就把&去掉若是是別名就把根據別名獲取真實名稱後面就不貼代碼了
   final String beanName = transformedBeanName(name);

   //最後的返回值
   Object bean;

   // 檢查是否已初始化
   Object sharedInstance = getSingleton(beanName);
  //若是已經初始化過了,且沒有傳args參數就表明是get,直接取出返回
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("...");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 這裏若是是普通Bean 的話,直接返回,若是是 FactoryBean 的話,返回它建立的那個實例對象
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // 若是存在prototype類型的這個bean
      if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
      }

      // 若是當前BeanDefinition不存在這個bean且具備父BeanFactory
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         String nameToLookup = originalBeanName(name);
      // 返回父容器的查詢結果
         if (args != null) {
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else {
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
      }

      if (!typeCheckOnly) {
         // typeCheckOnly 爲 false,將當前 beanName 放入一個 alreadyCreated 的 Set 集合中。
         markBeanAsCreated(beanName);
      }

      /* * 到這就要建立bean了 */
      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 先初始化依賴的全部 Bean, depends-on 中定義的依賴
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               // 檢查是否是有循環依賴
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               // 註冊一下依賴關係
               registerDependentBean(dep, beanName);
               // 先初始化被依賴項
               getBean(dep);
            }
         }

         // 若是是單例的
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  try {
                     // 執行建立 Bean,下面說
                     return createBean(beanName, mbd, args);
                  }
                  catch (BeansException ex) {
                     destroySingleton(beanName);
                     throw ex;
                  }
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         // 若是是prototype
         else if (mbd.isPrototype()) {
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               // 執行建立 Bean
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         // 若是不是 singleton 和 prototype 那麼就是自定義的scope、例如Web項目中的session等類型,這裏就交給自定義scope的應用方去實現
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     beforePrototypeCreation(beanName);
                     try {
                        // 執行建立 Bean
                        return createBean(beanName, mbd, args);
                     }
                     finally {
                        afterPrototypeCreation(beanName);
                     }
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   //檢查bean的類型
   if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
      try {
         return getTypeConverter().convertIfNecessary(bean, requiredType);
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

複製代碼

開始會先判斷bean存不存在,若是存在就直接返回了。若是不存在調用createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法了

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // 確保 BeanDefinition 中的 Class 被加載
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // 準備方法覆寫,若是bean中定義了 <lookup-method /> 和 <replaced-method />
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // 若是有代理的話直接返回
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }
   // 建立 bean
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean '" + beanName + "'");
   }
   return beanInstance;
}

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {

   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
    //若是是.factoryBean則從緩存刪除
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 實例化 Bean,這個方法裏面纔是終點,下面說
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   //bean實例
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
   //bean類型
   Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
   mbd.resolvedTargetType = beanType;

   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            // 循環調用實現了MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法
         // Spring對這個接口有幾個默認的實現,其中你們最熟悉的一個是操做@Autowired註解的
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

 
   // 解決循環依賴問題
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
    //當正在建立A時,A依賴B,此時經過(8將A做爲ObjectFactory放入單例工廠中進行early expose,此處B須要引用A,但A正在建立,從單例工廠拿到ObjectFactory,從而容許循環依賴
      addSingletonFactory(beanName, new ObjectFactory<Object>() {
         @Override
         public Object getObject() throws BeansException {
            return getEarlyBeanReference(beanName, mbd, bean);
         }
      });
   }

   Object exposedObject = bean;
   try {
      // 負責屬性裝配,很重要,下面說
      // 裝配屬性
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
         // 這裏是處理bean初始化完成後的各類回調,例如init-method、InitializingBean 接口、BeanPostProcessor 接口
         exposedObject = initializeBean(beanName, exposedObject, mbd);
      }
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
   //一樣的,若是存在循環依賴
   if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // 把bean註冊到相應的Scope中
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

複製代碼
  • populateBean((String beanName, RootBeanDefinition mbd, BeanWrapper bw)

這個方法完成bean內部屬性的注入

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
   // bean的全部屬性
   PropertyValues pvs = mbd.getPropertyValues();

   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         return;
      }
   }


   boolean continueWithPropertyPopulation = true;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 若是返回 false,表明不須要進行後續的屬性設值,也不須要再通過其餘的 BeanPostProcessor 的處理
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   if (!continueWithPropertyPopulation) {
      return;
   }

   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // 經過名字找到全部屬性值,若是是 bean 依賴,先初始化依賴的 bean。記錄依賴關係
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      // 經過類型裝配。複雜一些
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }

      pvs = newPvs;
   }

   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               // 這裏就是上方曾經提到過得對@Autowired處理的一個BeanPostProcessor了
               // 它會對全部標記@Autowired、@Value 註解的屬性進行設值
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }
   // 設置 bean 實例的屬性值
   applyPropertyValues(beanName, mbd, bw, pvs);
}

複製代碼
  1. finishRefresh()
protected void finishRefresh() {
  //看名字就知道了,清理剛纔一系列操做使用到的資源緩存
  clearResourceCaches();

  // 初始化LifecycleProcessor
  initLifecycleProcessor();

  // 這個方法的內部實現是啓動全部實現了Lifecycle接口的bean
  getLifecycleProcessor().onRefresh();

  //發佈ContextRefreshedEvent事件
  publishEvent(new ContextRefreshedEvent(this));

  // 檢查spring.liveBeansView.mbeanDomain是否存在,有就會建立一個MBeanServer
  LiveBeansView.registerApplicationContext(this);
}

複製代碼

3. 後記

這裏只是對於容器的初始化作了總體的分析,對於bean的建立和獲取還涉及到不少知識點。後面會專門講解

相關文章
相關標籤/搜索