Spring 原始碼(14)Spring Bean 的建立過程(5)

玲丶蹊發表於2022-05-13

到目前為止,我們知道Spring建立Bean物件有5中方法,分別是:

  • 使用FactoryBeangetObject方法建立
  • 使用BeanPostProcessor的子介面InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation方法建立
  • 設定BeanDefinitionSupplier屬性進行建立
  • 設定BeanDefinitionfactory-method進行建立
  • 使用全過程:getBean-->doGetBean-->createBean-->doCreateBean 反射進行建立

前面4中已經介紹,接下來介紹第5種,我們知道如果使用反射建立,那麼必然要知道使用建構函式進行例項化,因為使用建構函式能夠將帶有引數的設定進去。

SmartInstantiationAwareBeanPostProcessor 介面

在前面講過InstantiationAwareBeanPostProcessor 是用來提前例項化物件的,而SmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor 的子介面,他是用來幹啥呢?

createBeanInstance方法中的原始碼:

// 省略程式碼....
// 明確構造器從BeanPostProcessor中,對應的是 AutowiredAnnotationBeanPostProcessor
// 他是 SmartInstantiationAwareBeanPostProcessor 的子類,使用determineCandidateConstructors進行
// 解析建構函式
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  return autowireConstructor(beanName, mbd, ctors, args);
}
// 省略程式碼....

點進去:

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
  throws BeansException {

  if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        // 決定候選的建構函式
        Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
        if (ctors != null) {
          return ctors;
        }
      }
    }
  }
  return null;
}

可以看到這個介面是用來解析BeanClass的建構函式的,SmartInstantiationAwareBeanPostProcessor的實現類AutowiredAnnotationBeanPostProcessor,這個類是用來解析確定合適的建構函式,重點解析了@Autowired註解,並且還解析了@Value註解和@Lookup註解。

當解析出來建構函式之後,那麼就呼叫autowireConstructor方法進行例項化,解析時會new一個構造器解析器ConstructorResolver ,在解析factoryMehod時也是使用的這個類使用的是instantiateUsingFactoryMethod這個方法,並且解析factoryMethod更加複雜,需要判斷是否是靜態的工廠建立還是例項工廠建立,而自動裝配的構造解析相對來說簡單一些,使用autowireConstructor方法進行解析。

最終解析出構造方法和構造引數之後進行例項化:

// 使用合適的構造方法和構造引數進行例項化
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));

例項化:

private Object instantiate(
  String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {

  try {
    // 獲取例項化策略,一般使用 CglibSubClassingInstantiationStrategy
    InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
    if (System.getSecurityManager() != null) {
      return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                                           strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
                                           this.beanFactory.getAccessControlContext());
    }
    else {
      // 開始例項化
      return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
    }
  }
  catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Bean instantiation via constructor failed", ex);
  }
}

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
                          final Constructor<?> ctor, Object... args) {
  if (!bd.hasMethodOverrides()) {
    if (System.getSecurityManager() != null) {
      // use own privileged to change accessibility (when security is on)
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
        ReflectionUtils.makeAccessible(ctor);
        return null;
      });
    }
    // 例項化類,反射呼叫
    return BeanUtils.instantiateClass(ctor, args);
  }
  else {
    // 如果方法被覆蓋,lookup-method 和 replace-method
    return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
  }
}

如果前面的解析都沒有到Bean,那麼就會使用無參建構函式進行解析:

// 省略程式碼....
// Preferred constructors for default construction?
// 首選的構造器為預設的建立方式,使用了@Primary註解的為首選的建立物件方式
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
  return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
// 呼叫無參建構函式例項化物件
return instantiateBean(beanName, mbd);

例項化Bean

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
  try {
    Object beanInstance;
    if (System.getSecurityManager() != null) {
      beanInstance = AccessController.doPrivileged(
        (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
        getAccessControlContext());
    }
    else {
      // 例項化物件,使用反射進行建立
      beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
    }
    // 建立一個Bean的包裝器
    BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    // 初始化Bean的包裝器
    initBeanWrapper(bw);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(
      mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  }
}

這裡可以看到前面使用factoryMethodautowireConstructor 解析建構函式進行例項化還是使用無參建構函式進行例項化都是將Bean進行了包裝,那這個包裝有啥作用呢?

BeanWrapper的作用

我們先來看下前面的方法是怎麼建立BeanWrapper的:

factory-method 解析,ConstructorResolver#instantiateUsingFactoryMethod 方法:

public BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
		// 建立一個Bean的包裝器
		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
		// factoryBean
		Object factoryBean;
		// factory 工廠類
		Class<?> factoryClass;
		// 標識是否是靜態的工廠
		boolean isStatic;
        // 省略程式碼....
}  

SmartInstantiationAwareBeanPostProcessor子類AutowiredAnnotationBeanPostProcessor 解析出建構函式,然後使用ConstructorResolver#autowireConstructor 執行:

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
		// 建立一個包裝器
		BeanWrapperImpl bw = new BeanWrapperImpl();
		// 初始化包裝器
		this.beanFactory.initBeanWrapper(bw);
		// 建構函式
		Constructor<?> constructorToUse = null;
		// 構造引數
		ArgumentsHolder argsHolderToUse = null;
		// 需要使用的構造引數
		Object[] argsToUse = null;
		// 明確的構造引數不為空,則賦值給將要執行例項化的構造引數
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
        // 省略程式碼....
}

最終都是會進行轉換服務ConversionServicePropertyEditorRegistry的註冊,一個是用來進行屬性型別轉換的,一個是用來屬性值解析的:

protected void initBeanWrapper(BeanWrapper bw) {
  // 獲取轉換服務放到bean的包裝器中
  bw.setConversionService(getConversionService());
  // 註冊定製的屬性編輯器
  registerCustomEditors(bw);
}

在前面的文章中,介紹了這兩個如何使用,而且還自定義了屬性編輯器和型別轉換,需要的小夥伴可以去看看:

https://www.cnblogs.com/redwinter/p/16167214.htmlhttps://www.cnblogs.com/redwinter/p/16241328.html

到這裡Bean的例項化就完成了,接著往下看原始碼:

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

  // Instantiate the bean.
  BeanWrapper instanceWrapper = null;
  // 從快取中獲取FactoryBean的Bean物件
  if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
    // 例項化物件
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  // 從包裝器中獲取Bean物件
  Object bean = instanceWrapper.getWrappedInstance();
  // 從包裝器中獲取Bean型別
  Class<?> beanType = instanceWrapper.getWrappedClass();
  if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
  }

  // Allow post-processors to modify the merged bean definition.
  synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
      try {
        // 合併Bean
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Post-processing of merged bean definition failed", ex);
      }
      mbd.postProcessed = true;
    }
  }
}

點進去:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
      MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
      // 執行合併BeanDefinition
      bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
  }
}

可以看到這裡出現了一個介面MergedBeanDefinitionPostProcessor,這個介面也是BeanPostProcessor的子介面,那他到底是幹啥用的呢?

MergedBeanDefinitionPostProcessor 介面

點選發現這個介面的實現類全是跟註解相關的,而最重要的是CommonAnnotationBeanPostProcessor實現類,在建構函式中設定了兩個註解:@PostConstruct@PreDestroy ,一個是在初始化完之後呼叫,一個是容器銷燬時呼叫。

未完待續.....

相關文章