Spring-IOC整體設計與源碼分析

最近讀完《Spring技術內幕》一書,雖然此書評價貌似不高,但邊看書邊讀源碼,感覺還是有點收穫,至少爲閱讀Spring源碼提供了思路。然後這篇文章就記錄一下這幾天看Spring IOC這塊的源碼以及整體思路。

1、 BeanFactory與ApplicationContext

在Spring的IOC容器設計中,主要由兩個容器系列:

  • 實現BeanFactory接口的簡單容器,提供了完整IoC容器服務支持,默認延遲初始化(lazy-load)——只有訪問託管對象的時候,纔會對對象進行初始化和依賴注入操作。
  • 實現ApplicationContext接口的集成容器,在BeanFactory的基礎上增加了更多複雜的企業級功能,容器啓動時,就默認把所有的單例對象實例化完成。

BeanFactory

2、 最簡單的容器StaticListableBeanFactory

整個Spring容器中最簡單的實現就是StaticListableBeanFactory,從它開始分析最合適不過了。

public class StaticListableBeanFactory implements ListableBeanFactory {

    /** <BeanName, BeanInstance>的映射 */
    private final Map<String, Object> beans;
  
  // 默認構造會創建一個空的Map,自行調用addBean方法添加到容器中
    public StaticListableBeanFactory() {
        this.beans = new LinkedHashMap<String, Object>();
    }

  // 由外部預初始化一個Map
    public StaticListableBeanFactory(Map<String, Object> beans) {
        Assert.notNull(beans, "Beans Map must not be null");
        this.beans = beans;
    }

  // addBean就是簡單的將name和instance加入到Map中
  public void addBean(String name, Object bean) {
        this.beans.put(name, bean);
    }
  
  // 根據beanName從容器中獲取Bean對象
    @Override
    public Object getBean(String name) throws BeansException {
    // 處理"&"開頭的BeanName(dereference解引用)
        String beanName = BeanFactoryUtils.transformedBeanName(name);
        Object bean = this.beans.get(beanName);

        if (bean == null) {
      // Bean不存在
            throw new NoSuchBeanDefinitionException(beanName,
                    "Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
        }

        if (BeanFactoryUtils.isFactoryDereference(name) && !(bean instanceof FactoryBean)) {
          // BeanName以"&"開頭,但Bean不是FactoryBean
            throw new BeanIsNotAFactoryException(beanName, bean.getClass());
        }

        if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
      // Bean是FactoryBean,但BeanName不是"&"開頭,則由FactoryBean創建Bean對象
            try {
                return ((FactoryBean<?>) bean).getObject();
            }
            catch (Exception ex) {
                throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
            }
        }
        else {
      // 其他情況直接返回Bean
            return bean;
        }
    }
  
  // 其餘getBean方法(byName,byType)最終都是調用上面的getBean方法
  ...

  // 判斷bean是否爲共享單例,也就是說調用getBean方法會始終返回同一個對象
  // 注意:返回false,不一定說明是prototype的Bean,應該調isPrototype去顯示檢查是否是原型對象
    @Override
    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        Object bean = getBean(name);
        return (bean instanceof FactoryBean && ((FactoryBean<?>) bean).isSingleton());
    }

  // 判斷bean是否爲原型實例,也就是說調用getBean方法會始終返回一個獨立的新實例
  // 注意:返回false,不應定說明是singleton的Bean,應該調isSingleton去顯示檢查是否是單例對象
    @Override
    public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
        Object bean = getBean(name);
        return ((bean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) bean).isPrototype()) ||
                (bean instanceof FactoryBean && !((FactoryBean<?>) bean).isSingleton()));
    }

  // 獲取Bean的類型
    @Override
    public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        String beanName = BeanFactoryUtils.transformedBeanName(name);

        Object bean = this.beans.get(beanName);
        if (bean == null) {
            throw new NoSuchBeanDefinitionException(beanName,
                    "Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
        }

        if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            // 如果是FactoryBean, 去看Factory創建的是什麼類型的Bean.
            return ((FactoryBean<?>) bean).getObjectType();
        }
        return bean.getClass();
    }
  ...
}

3、 特殊的Bean對象——FactoryBean

Spring容器中有兩種Bean:普通Bean和工廠Bean。Spring直接使用前者,後者以工廠模式生產Bean對象,並由Spring管理。

Spring設計FactoryBean的目的是爲了將複雜對象的相關構造邏輯封裝在類中,比如常見的ProxyFactoryBean。

另外一個目的是爲了讓我們能將依賴注入到一些第三方庫的對象中,比如LocalContainerEntityManagerFactoryBean負責JPA的EntityManagerFactory的創建,ThreadPoolExecutorFactoryBean負責線程池的創建,ForkJoinPoolFactoryBean負責ForkJoinPool線程池的創建,ScheduledExecutorFactoryBean負責調度線程池的創建…

但是Spring3.0基於Java註解的配置開始流行之後,這些FactoryBean基本都用不到了,這些對象我們可以通過@Bean方法的形式配置。

我個人大膽的猜測,FactoryBean是爲了早期以XML配置對象的方式而設計的。

通過在BeanName前加上&前綴我們能拿到FactoryBean工廠本身。比如:

public class MyBeanFactoryBean implements FactoryBean<MyBean> {
 
    public MyBean getObject() throws Exception {
        return new MyBean();
    }
 
    public Class<?> getObjectType() {
        return MyBean.class;
    }
}

// 直接通過beanName獲取的是工廠創建的MyBean對象
beanFactory.getBean("myBean");
// 加&前綴獲取的是MyBeanFactoryBean這個工廠本身
beanFactory.getBean("&myBean");

經常被問的一個問題是BeanFactory與FactoryBean的區別,用一句話總結起來:

BeanFactory代表Spring容器,而FactoryBean表示工廠類,其創建的對象被獲取後作爲容器中的Bean註冊

4、 核心容器DefaultListableBeanFactory

Spring IOC體系結構中最核心的容器實現類就是DefaultListableBeanFactory,它實現了ConfigurableListableBeanFactoryBeanDefinitionRegistry兩個接口的功能。

DefaultListableBeanFactory

4.1 、BeanDefinition、BeanDefinitionRegistry、BeanDefinitionReader

BeanDefinition用於描述一個Bean實例的scope、是否爲懶加載、生命週期方法(init、destroy)、屬性值、構造參數值以及組件依賴等信息。

BeanDefinition

BeanDefinitionRegistry就是BeanDefinition的註冊表,提供了registerBeanDefinition(beanName, beanDefinition)removeBeanDefinition(beanName)等相關方法。

BeanDefinitionRegistry

BeanDefinitionReader負責從Properties、Xml、Groovy等配置文件中讀取BeanDefinition,並將其註冊到BeanDefinitionRegistry中。

BeanDefinitionReader

4.2、基於Java註解的配置

AnnotationConfigRegistry

Spring3.0之前只支持@Component、@Controller、@Service、@Repository這幾個組件級的註解。

Spring3.0開始支持Java註解配置Bean對象,也就是通過@Configuration配置類中方法上的@Bean註解來定義Bean對象。

其中Bean被加入到Spring容器有兩種方式:

1、register()方法直接以組件類的方式註冊AnnotatedGenericBeanDefinition到容器中,具體實現在AnnotatedBeanDefinitionReader中;

2、scan()方法通過掃描包下的所有組件類以批量的方式註冊若干個ScannedGenericBeanDefinition到容器中,具體實現在ClassPathBeanDefinitionScanner中;

如果註冊的是@Configuration註解的類,則在ConfigurationClassPostProcessor處理器中將所有@Bean註解方法的Bean註冊到容器中,這部分內容後面會講BeanFactoryPostProcessor的時候再詳細解析。

5、可配置的ConfigurableListableBeanFactory

ConfigurableListableBeanFactory

ConfigurableListableBeanFactory結合了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory三個接口的功能。這三個接口也分別代表了Spring容器提供的三大基本功能:

ListableBeanFactory:根據類型或註解查找Bean

AutowireCapableBeanFactory:解析Bean的依賴關係並進行自動裝配

ConfigurableBeanFactory:爲容器提供了配置接口,以拓展容器的功能

我們想要拓展Spring IOC容器的功能主要就是通過ConfigurableBeanFactory開出的幾個接口實現的:

5.1、BeanExpressionResolver

ConfigurableBeanFactory有兩個關於Spring EL表達式的方法:

    void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);
    BeanExpressionResolver getBeanExpressionResolver();

在Spring中BeanExpressionResolver的實現是StandardBeanExpressionResolver

BeanExpressionResolver

public class StandardBeanExpressionResolver implements BeanExpressionResolver {
  /// ...
  /** 該方法用於解析Spring EL表達式 **/
  public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
        if (!StringUtils.hasLength(value)) {
            return value;
        }
        try {
            Expression expr = this.expressionCache.get(value);
            if (expr == null) {
                expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
                this.expressionCache.put(value, expr);
            }
            StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
            if (sec == null) {
                sec = new StandardEvaluationContext(evalContext);
        ///...做了一堆的配置
                customizeEvaluationContext(sec);
                this.evaluationCache.put(evalContext, sec);
            }
            return expr.getValue(sec);
        }
        catch (Throwable ex) {
            throw new BeanExpressionException("Expression parsing failed", ex);
        }
    }

  // StandardBeanExpressionResolver提供了一個方法允許我們進行重載
    protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
    }
}

StandardBeanExpressionResolver提供了一個customizeEvaluationContext方法允許我們重載,我們唯一能做的就是對StandardEvaluationContext進行一些自定義配置。

5.2、Scope

Spring容器爲我們提供了SCOPE_SINGLETONSCOPE_PROTOTYPE兩種基本的Scope,它還允許我們註冊自己的Scope。比如Web應用中會用到的requestsession兩個Scope,另外Spring還提供了很多基礎的Scope給我們,如線程級別SimpleThreadScope、事務級別的SimpleTransactionScope

Spring提供的Scope

通常我們往容器中註冊Scope只需調用beanFactory.registerScope方法即可,另外Spring提供了一個BeanFactoryPostProcessor給我們——CustomScopeConfigurer。

關於BeanFactoryPostProcessor後面有一部分會介紹。

5.3、ConversionService

ConversionService,顧名思義,就是Spring提供給我們的類型轉換服務。它主要有幾種用途,解析配置文件中字符串,解析BeanDefinition中的property並綁定到對象中(DataBinder),解析Web應用中的請求參數並綁定到Controller的入參對象中(WebDataBinder),解析Spring EL表達式中的字面量。

ConversionService

除了ConversionService,ConfigurableBeanFactory還提供了PropertyEditorRegistrarTypeConverterStringValueResolver等接口用於處理Bean對象和類型轉換。

關於Spring Converter的內容可以參考這幾篇教程:

https://www.baeldung.com/spring-type-conversions

https://www.baeldung.com/spring-mvc-custom-data-binder

https://www.baeldung.com/spring-mvc-custom-property-editor

5.4、BeanPostProcessor

這個接口是用於擴展Spring功能的核心接口,事實上Spring容器本身的很多功能特性就是通過這個接口豐富的。

BeanPostProcessor有兩個方法:

public interface BeanPostProcessor {
  // 初始化方法之前調用
  Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  // 初始化方法之後調用
  Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

很明顯我們只要找到SpringBean什麼時候初始化,就知道這兩個方法什麼時候被調用,Spring Bean的初始化分爲四步:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {
  /// ...
  /// 這裏是整個初始化過程的代碼
  protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 第一步:調用Aware方法
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

    // 第二步:調用BeanPostProcessor的postProcessBeforeInitialization方法
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

    // 第三步:調用初始化方法
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
    // 第四步:調用BeanPostProcessor的postProcessAfterInitialization方法
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }
  ///...
}
  1. 第一步:調用Aware方法
       private void invokeAwareMethods(final String beanName, final Object bean) {
       /// 如果bean對象實現了相應的Aware接口,那這裏會調用三種Aware方法:
       /// BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
           if (bean instanceof Aware) {
               if (bean instanceof BeanNameAware) {
                   ((BeanNameAware) bean).setBeanName(beanName);
               }
               if (bean instanceof BeanClassLoaderAware) {
                   ClassLoader bcl = getBeanClassLoader();
                   if (bcl != null) {
                       ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                   }
               }
               if (bean instanceof BeanFactoryAware) {
                   ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
               }
           }
       }
  1. 第二步:調用BeanPostProcessor.postProcessBeforeInitialization方法
       public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
               throws BeansException {
       /// 這個很簡單:就是拿到BeanFactory裏的所有BeanPostProcessor
       /// 然後依次調用postProcessBeforeInitialization方法
           Object result = existingBean;
           for (BeanPostProcessor processor : getBeanPostProcessors()) {
               Object current = processor.postProcessBeforeInitialization(result, beanName);
               if (current == null) {
                   return result;
               }
               result = current;
           }
           return result;
       }
  1. 第三步:調用bean對象的init方法
      protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
              throws Throwable {
  
      /// 先看有沒有實現Spring定義的InitializingBean接口
      /// 如果有的話就調用InitializingBean的afterPropertiesSet方法
          boolean isInitializingBean = (bean instanceof InitializingBean);
          if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
              if (logger.isTraceEnabled()) {
                  logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
              }
              if (System.getSecurityManager() != null) {
                  try {
                      AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                          ((InitializingBean) bean).afterPropertiesSet();
                          return null;
                      }, getAccessControlContext());
                  }
                  catch (PrivilegedActionException pae) {
                      throw pae.getException();
                  }
              }
              else {
                  ((InitializingBean) bean).afterPropertiesSet();
              }
          }
  
      /// 然後調用自定義的init方法
      /// 這個init方法是xml或@Bean註解配置的init-method屬性
          if (mbd != null && bean.getClass() != NullBean.class) {
              String initMethodName = mbd.getInitMethodName();
              if (StringUtils.hasLength(initMethodName) &&
                      !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                      !mbd.isExternallyManagedInitMethod(initMethodName)) {
                  invokeCustomInitMethod(beanName, bean, mbd);
              }
          }
      }
  

這裏也許會有人想到使用JSR-250規範中定義的@PostConstruct註解進行初始化。

Spring提供了CommonAnnotationBeanPostProcessorInitDestroyAnnotationBeanPostProcessor來處理JavaEE標準中的註解,如@PostConstruct、@PreDestroy、@Resource。

在InitDestroyAnnotationBeanPostProcessor中可以看到它是通過實現BeanPostProcessor#postProcessBeforeInitialization方法並在其中調用Bean的@PostConstruct註解方法的:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try {
      /// 這裏的initMethod就是通過@PostConstruct註解解析出來的方法
      metadata.invokeInitMethods(bean, beanName);
   }
   catch (InvocationTargetException ex) {
      throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
   }
   return bean;
}

所以關於初始化方法的調用順序是:

@PostConstruct==>InitializingBean.afterPropertiesSet==>Xml或@Bean中定義的init-method

而且Bean中@PostConstruct方法可以定義多個,但InitializingBean因爲是接口所以afterPropertiesSet只有一個方法,init-method也只能有一個。

關於Spring初始化的過程可以參考這篇教程

  1. 第四步:調用BeanPostProcessor.postProcessAfterInitialization方法

        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
        /// 這個很簡單:就是拿到BeanFactory裏的所有BeanPostProcessor
        /// 然後依次調用postProcessBeforeInitialization方法
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

用一張圖總結一下:

initializeBean

5.5、BeanPostProceesor的常見實現

BeanPostProceesorImpl

Spring內部實現各種Aware的ApplicationContextAwareProcessor;

Web應用中裝配ServletContext的ServletContextAwareProcessor;

類加載時編織AspectJ切面的LoadTimeWeaver被LoadTimeWeaverAwareProcessor裝配;

關於加載時編織參考Spring官方文檔AspectJ官方文檔

另外還有幾個基於AOP實現的BeanPostProceesor,最常用的就是@Async註解實現異步方法,而這個就是AsyncAnnotationBeanPostProcessor處理器實現的。

關於Spring異步方法的使用可以參考這篇教程

5.6、BeanPostProcessor的子接口

BeanPostProcessor

BeanPostProcessor有三個字接口:

1、InstantiationAwareBeanPostProcessor:添加了實例化對象的回調方法,以及屬性值被自動裝配時的回調;

2、DestructionAwareBeanPostProcessor:添加了銷燬對象前的回調方法;

3、MergedBeanDefinitionPostProcessor:合併BeanDefinition後調用;

既然InstantiationAwareBeanPostProcessor是實例化和屬性自動裝配的回調,讓我們看一下這塊代碼:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {
  ///...
  // Spring創建Bean對象的整個過程
  protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   RootBeanDefinition mbdToUse = mbd;

   /// 解析並加載BeanDefinition中定義的Class
   /// ... 代碼省略

      /// ...省略異常處理代碼
      // 第一步:
      // 調用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         // Processor的方法可能返回一個代理對象,
         // 比如Spring AOP的自動代理(@EnableAspectJAutoProxy)。
         // 這種情況比較少,可以不考慮
         return bean;
      }
    
      /// ...省略異常處理代碼
      /// 根據BeanDefinition創建對象
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      return beanInstance;
  }
    
  /// 調用內部的創建方法  
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // 第二步: 實例化Bean對象
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 調用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
    // 讓Processor對BeanDefinition最後再進行一些處理
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
        /// ...省略異常處理代碼
              applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        // 將Bean對象緩存起來以解決循環引用的問題
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
    /// ...省略異常處理代碼
    // 填充Bean的屬性
      populateBean(beanName, mbd, instanceWrapper);
    // 初始化Bean對象
      exposedObject = initializeBean(beanName, exposedObject, mbd);

        ///...

    /// ...省略異常處理代碼
        // 註冊Disposable接口和DestructionAwareBeanPostProcessor的DisposableBeanAdapter
      registerDisposableBeanIfNecessary(beanName, bean, mbd);

        return exposedObject;
    }
  
  protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        ///...

        // 調用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // 自動裝配對象
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // 根據名稱自動裝配
            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) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
        /// 調用InstantiationAwareBeanPostProcessor.postProcessPropertyValues
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        if (pvs != null) {
      // 將依賴的Bean對象注入到新創建的Bean中
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }
  ///...
}

至此,創建Bean的整個過程可以總結爲下圖:

CreateBean

6. 功能更強大的容器——ApplicationContext

ApplicationContext繼承圖

ApplicationContext在BeanFactory容器的基礎上繼承了另外四個接口:

  1. EnvironmentCapable接口:暴露了應用當前的環境配置信息的Environment接口。Environment提供了profilesproperties兩方面的配置信息:

    profiles指的是一組Bean的集合,這些Bean可以在xml中配置profile或着使用@Profile註解。Environment對於Profile來說,就是用於決定當前哪個profile被激活了,那個profile應該默認被激活。

    Spring Profile的相關內容可以參考這篇教程

    properties在應用中扮演着重要角色,主要來源形式有:properties文件、JVM系統參數、系統環境變量、JDNI、Servlet容器參數等。

  2. MessageSource接口:提供了消息的參數化與國際化,避免了開發人員編寫大量額外的代碼處理各種複雜的情況。

    在SpringBoot中使用MessageSource處理校驗報錯信息,可以參考這篇教程

  3. ApplicationEventPublisher接口:爲Spring容器提供了事件發佈功能。ApplicationContext容器通過代理ApplicationEventMulticaster實現事件發佈功能(具體可以參看AbstractApplicationContext的相關代碼)。Spring容器本身也會發布各種事件,如ContextRefreshedEvent,ContextStartedEvent,RequestHandledEvent等。

    Spring Events的相關內容可以參考官方教程這篇教程,Spring容器內置事件可參考這篇教程

  4. ResourcePatternResolver接口:提供瞭解析資源路徑的功能。如/WEB-INF/*-context.xmlclasspath*:context.xml這樣的路徑。

其次就是中間過渡的ConfigurableApplicationContext接口:

ConfigurableApplicationContext在ApplicationContext的基礎上提供了一些配置接口,和ConfigurableBeanFactory類似,ConfigurableApplicationContext將配置和生命週期方法封裝在此主要是爲了避免對客戶端代碼可見,ConfigurableApplicationContext接口的方法應該只在應用啓動和關閉的時候調用。這裏面有這麼幾個方法比較重要:

// 啓動容器加載配置並實例化所有的單例Bean
// 所有ApplicationContext容器必須refresh()了才能使用
void refresh();
// 關閉容器釋放所有相關資源,包括銷燬所有緩存的單例Bean
void close();

6.1、AbstractApplicationContext

先讓我們看一下refresh()方法。

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 準備ApplicationContext以進行refresh
            prepareRefresh();

            // 通知子類去刷新內部的BeanFactory
      // AbstractApplicationContext提供了三個抽象方法由子類去實現:
      // void refreshBeanFactory()
      // void closeBeanFactory()
      // ConfigurableListableBeanFactory getBeanFactory()
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 對這個BeanFactory進行配置
            prepareBeanFactory(beanFactory);

            try {
                // 讓子類再對BeanFactory進行相應的配置
                postProcessBeanFactory(beanFactory);

                // 調用BeanFactoryPostProcessor
        // 並找到beanFactory容器中實現了BeanFactoryPostProcessor接口的bean,一起調用
        // 主要這個這個接口和BeanPostProcessor有所區別
                invokeBeanFactoryPostProcessors(beanFactory);

                // 找出beanFactory中實現了BeanPostProcessor的Bean
        // 並將它們以BeanPostProcessor的角色註冊到beanFactory中
                registerBeanPostProcessors(beanFactory);

                // 初始化用於i18n的MessageSource
                initMessageSource();

                // 初始化用於事件分發的ApplicationEventMulticaster
                initApplicationEventMulticaster();

                // 讓子類做一些其他的初始化,比如web應用中要初始化ThemeSource
                onRefresh();

                // 找到容器中所有的ApplicationListener並將其註冊到ApplicationEventMulticaster中
                registerListeners();

                // 對BeanFactory進行最後的初始化,然後凍結配置,預初始化所有的單例對象
                finishBeanFactoryInitialization(beanFactory);

                // 最後一步:完成最後的刷新工作併發布ContextRefreshedEvent事件
                finishRefresh();
            }

            ///...
        }
    }

AbstractApplicationContext提供了很多模版方法給子類去實現,接下來我們看一下最主要的兩個子類。

6.2、GenericApplicationContext與AbstractRefreshableApplicationContext

Spring容器的兩個體系

GenericApplicationContextRefreshableApplicationContext兩個體系內的容器實現本質上都是代理了DefaultListableBeanFactory提供的功能。

兩者的區別在於GenericApplicationContext只能refresh()一次,而RefreshableApplicationContext允許refresh()多次。

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;

  /// ...
    public GenericApplicationContext() {
    // 在構造的時候就創建了beanFactory
    // 之後的refresh()等操作都是對這個beanFactory進行操作
        this.beanFactory = new DefaultListableBeanFactory();
    }
  ///...
}

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
  ///...
  
    @Nullable
    private DefaultListableBeanFactory beanFactory;
  
  public AbstractRefreshableApplicationContext() {
    }
  
  // 實現AbstractApplicationContext提供的模版方法
  // 每次refresh()都會重新創建新的BeanFactory
  protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
      // 銷燬已有的容器
            destroyBeans();
            closeBeanFactory();
        }
        try {
      // 創建新的容器
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(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);
        }
    }
  
    protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }
  ///...
}

6.3、BeanFactoryPostProcessor

不要將BeanFactoryPostProcessor和前面的BeanPostProcessor搞混,這個接口是BeanFactory初始化後的回調接口。

BeanFactoryPostProcessor可以與BeanDefinition進行交互並進行修改,但不能與Bean實例交互。這樣做可能會導致bean過早實例化,從而違反了容器規則並造成了意外的副作用。如果需要與bean實例交互,請考慮實現BeanPostProcessor

常見的BeanFactoryPostProcessor有CustomScopeConfigurer(自定義Scope)、CustomAutowireConfigurer(自定義@Qualifier)、CustomEditorConfigurer(自定義PropertyEditor)。它們都是用來擴展BeanFactory功能的。還有一個EventListenerMethodProcessor是用來處理@EventListener註解的。

BeanFactoryPostProcessor另一個核心的實現類就是ConfigurationClassPostProcessor,它是用來解析@Configuration註解類的處理器。

BeanFactoryPostProcessor

前面提到過Spring3.0開始支持@Configuration的配置,而它是由AnnotationConfigApplicationContext透出的,所以我們從這個類開發分析。

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    private final AnnotatedBeanDefinitionReader reader;

    private final ClassPathBeanDefinitionScanner scanner;
  
    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
  ///...
  
     @Override
    public void register(Class<?>... componentClasses) {
        Assert.notEmpty(componentClasses, "At least one component class must be specified");
        this.reader.register(componentClasses);
    }
  
    @Override
    public void scan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        this.scanner.scan(basePackages);
    }

  ///...
}

這裏的AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner都是爲了解析@Component註解並註冊BeanDefinition。

當然這裏的@Component還包括@Repository、@Service、@Controller、@Configuration這幾個複合註解。

Annotate和Class在讀取和掃描過程中都會去調用AnnotationConfigUtilsregisterAnnotationConfigProcessors方法註冊Spring的註解處理器,其中包括:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, Object source) {

   DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
   if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
         beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
         beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
   }

   Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

  // 註冊@Configuration、@Bean、@Import、@ComponentScan等註解的ConfigurationClassPostProcessor
   if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

  // 註冊@Autowired、@Value等註解的AutowiredAnnotationBeanPostProcessor
   if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

  // 註冊處理@Required註解的RequiredAnnotationBeanPostProcessor
   if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

  // 檢查是否有JSR-250的依賴
  // 有則註冊處理@PostConstruct、@PreDestroy、@Resource等註解的
  // CommonAnnotationBeanPostProcessor.
   if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   // 檢查JPA的依賴, 有則註冊處理@PersistenceUnit、@PersistenceContext註解的
   // PersistenceAnnotationBeanPostProcessor.
   if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition();
      try {
         def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
               AnnotationConfigUtils.class.getClassLoader()));
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      }
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

  // 註冊處理@EventListener註解的EventListenerMethodProcessor
   if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
   }
  // 爲@EventListener註解的方法提供一個事件類型適配器
   if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
   }

   return beanDefs;
}

這裏我們主要關注ConfigurationClassPostProcessor,因爲它實現了BeanDefinitionRegistryPostProcessor接口,所以它會回調兩次:

1、先回調BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry方法,由ConfigurationClassParser解析出所有的ConfigurationClass,再由ConfigurationClassBeanDefinitionReader將所有的ConfigurationClass讀取並將BeanDefinition註冊到容器中。

2、然後回調BeanFactoryPostProcessor.postProcessBeanFactory方法,其中ConfigurationClassEnhancer使用Cglib對@Configuration類進行動態代理增強,主要是爲了調用@Bean註解方法時由BeanFactory負責創建對象並將其放入容器中。

@Configuration
public class DemoConfiguration {
    
    @Bean
    public ObjectA a(){
        return new ObjectA();
    }
    
    @Bean
    public ObjectB b(){
      // 正因爲ConfigurationClassEnhancer
      // 所以調用a()方法時會從BeanFactory中取出bean,而不是每次創建一個新對象
        return new ObjectB(a());
    }
}

對於ConfigurationClassPostProcessor更詳細的源碼分析請參考這兩篇文章:

ConfigurationClassPostProcessor源碼分析

Spring Boot源碼分析

其中比較重要的是@Import註解的處理,因爲Spring中很多@EnableXxx註解都是基於這個實現的。

@Import註解內可以填三種類型:

1、@Configuration註解類,2、ImportSelector接口實現類,3、ImportBeanDefinitionRegistrar接口實現類

@EnableXxx => @Import(XxxConfiguration ==> @Configuration) => XxxBeanPostProcessor

​ eg. @EnableScheduling

​ => @Import(XxxSelector ==> ImportSelector)

​ eg. @EnableAsync、@EnableDubboConfig

​ => @Import(XxxRegistrar ==> ImportBeanDefinitionRegistrar)

​ eg. @EnableAspectJAutoProxy、@EnableJpaAuditing、@EnableJpaRepositories

看一下這塊的代碼:

    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
            Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {

        if (importCandidates.isEmpty()) {
            return;
        }

        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
            this.importStack.push(configClass);
            try {
                for (SourceClass candidate : importCandidates) {
          // 處理ImportSelector實現類
                    if (candidate.isAssignable(ImportSelector.class)) {
                        Class<?> candidateClass = candidate.loadClass();
                        ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                        ParserStrategyUtils.invokeAwareMethods(
                                selector, this.environment, this.resourceLoader, this.registry);
                        if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
              // 如果實現的是DeferredImportSelector接口則延遲處理
                            this.deferredImportSelectors.add(
                                    new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                        }
                        else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
              // 直接拿到import的類,遞歸處理一下
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    }
          // 處理ImportBeanDefinitionRegistrar實現類
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                        ParserStrategyUtils.invokeAwareMethods(
                                registrar, this.environment, this.resourceLoader, this.registry);
            // 註解將ImportBeanDefinitionRegistrar放到configClass中
            // 最後由ConfigurationClassBeanDefinitionReader處理
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }
                    else {
                        // 否則當作@Configuration註解的類處理
                        this.importStack.registerImport(
                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        processConfigurationClass(candidate.asConfigClass(configClass));
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                        configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }

至此已將Spring IOC的大部分核心內容的整體結構理清楚了,更多細節上的知識還需要查看源碼去理解。

參考資料:

https://www.baeldung.com/spring-factorybean

https://www.baeldung.com/spring-profiles

https://spring.io/blog/2007/06/05/more-on-java-configuration

https://spring.io/blog/2014/11/04/a-quality-qualifier

https://spring.io/blog/2011/08/09/what-s-a-factorybean

https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2

https://spring.io/blog/2010/01/05/task-scheduling-simplifications-in-spring-3-0

https://spring.io/blog/2011/02/17/spring-3-1-m1-introducing-featurespecification-support

https://spring.io/blog/2016/03/04/core-container-refinements-in-spring-framework-4-3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章