前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Spring源码】- 03 Spring IoC容器启动之Bean创建流程

【Spring源码】- 03 Spring IoC容器启动之Bean创建流程

作者头像
Reactor2020
发布2023-03-22 18:56:15
2950
发布2023-03-22 18:56:15
举报
文章被收录于专栏:【云原生 • Prometheus】

上篇已经分析完refresh()中大部分方法,也已经把Bean解析成BeanDefinition注册到IoC容器中,refresh还剩下一个非常重要的方法,就是下面将要分析的:finishBeanFactoryInitialization,用以完成Bean创建、依赖注入和初始化等工作。

代码语言:javascript
复制
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
 // 初始化类型转换器
 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));
 }

 // 占位符表达式解析器,比如解析@Value("${test.name}")
 if (!beanFactory.hasEmbeddedValueResolver()) {
  beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
 }

 // 初始化LoadTimeWeaverAware Bean,getBean则是让实现LoadTimeWeaverAware的对象提前实例化
 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
 for (String weaverAwareName : weaverAwareNames) {
  getBean(weaverAwareName);
 }

 //停止使用临时的类加载器
 beanFactory.setTempClassLoader(null);

 // 冻结所有的BeanDefinition定义,不期望以后会被修改或进一步处理,因为马上要创建Bean实例对象了
 beanFactory.freezeConfiguration();

 // 实例化所有的non-lazy-init 单例
 beanFactory.preInstantiateSingletons();
}

关键代码是最后一句:beanFactory.preInstantiateSingletons()

preInstantiateSingletons

代码语言:javascript
复制
@Override
public void preInstantiateSingletons() throws BeansException {

 // 获取到所有BeanDefinition名称,后面用于遍历处理
 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

 // 遍历触发每个BeanDefinition实例化
 for (String beanName : beanNames) {
  //getMergedLocalBeanDefinition()可以简单理解成获取BeanDefinition即可
        //主要涉及到将其它类型的BeanDefinition统一转成成RootBeanDefinition或继承关系导致的多个BeanDefinition合并成一个
  RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  /**
  * 作用域是singleton,且不是abstract和lazy-init,才会执行初始化
  * 只有singleton的Bean才会提前实例化好,其它作用域和lazy属性的Bean都是在使用时调用getBean()方法时才会被创建
  */
  if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
   /**
   * 是否为FactoryBean,不是的话直接getBean(beanName),也就是实例化
   * 如果是FactoryBean,走IF语句块
   */
   if (isFactoryBean(beanName)) {
    //通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    if (bean instanceof FactoryBean) {
     final FactoryBean<?> factory = (FactoryBean<?>) bean;
     //判断这个FactoryBean是否希望急切的初始化
     boolean isEagerInit;
     if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
      isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
          ((SmartFactoryBean<?>) factory)::isEagerInit,
        getAccessControlContext());
     }
     else {
      isEagerInit = (factory instanceof SmartFactoryBean &&
        ((SmartFactoryBean<?>) factory).isEagerInit());
     }
     if (isEagerInit) {
      getBean(beanName);
     }
    }
   }
   else {
    //非FactoryBean实例化
    getBean(beanName);
   }
  }
 }

    /**
 * 这里出现了另一个扩展点:SmartInitializingSingleton,用于所有Singleton实例创建全部完成(包括各种依赖注入、初始化等)后,
 * 去执行SmartInitializingSingleton#afterSingletonsInstantiated回调方法
 */
 for (String beanName : beanNames) {
  Object singletonInstance = getSingleton(beanName);
  // 如果实例实现了SmartInitializingSingleton,执行afterSingletonsInstantiated方法。
  if (singletonInstance instanceof SmartInitializingSingleton) {
   final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
   if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
     smartSingleton.afterSingletonsInstantiated();
     return null;
    }, getAccessControlContext());
   }
   else {
    smartSingleton.afterSingletonsInstantiated();
   }
  }
 }
}

FactoryBean创建走的是getBean(),内部又会委托给doGetBean()方法。

注意,这里出现了另一个重要的扩展点:SmartInitializingSingleton#afterSingletonsInstantiated,从代码上看就是所有非Lazy类型的Singleton实例都被全部创建完成后,会触发回调。案例可参见EventListenerMethodProcessor:待所有Singleton创建完毕,找到其中标注了@EventListener注解的方法,利用反射和DefaultEventListenerFactory为其创建ApplicationListener,并添加到事件派发器的缓存中。

doGetBean

代码语言:javascript
复制
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

 //解析beanName,主要是解析别名、去掉FactoryBean的前缀“&”
 final String beanName = transformedBeanName(name);
 Object bean;

 /**
 * 通过singletonObjects()方法先尝试从缓存中获取bean实例,获取不到再走后面创建的流程,通过缓存解决循环依赖问题
 *
 * 获取到有两种情况:
 *   一种是Bean创建完成后,会存储到该缓存中
 *   另一种是未创建完成,但先预存到一个单独的缓存中,这种是针对可能存在循环引用的情况的处理。
 *  如A引用B,B又引用了A,因而在初始化A时,A会先调用构造函数创建出一个实例,在依赖注入B之前,现将A实例缓存起来
 *  然后在初始化A时,依赖注入阶段,会触发初始化B,B创建后需要依赖注入A时,先从缓存中获取A(这个时候的A是不完整的),避免循环依赖的问题出现。
 */
 Object sharedInstance = getSingleton(beanName);
 if (sharedInstance != null && args == null) {
  /**
  * 这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例。
  * 普通Bean会直接返回sharedInstance本身
  * preInstantiateSingletons方法中也有处理FactoryBean分支,但是那是针对Singleton且提前实例化情况,
  * 对于Lazy类型的FactoryBean,那个流程是走不到的,而是在getBean时才会创建,所以这里还要处理FactoryBean
  */
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 }
 //缓存没有则创建
 else {
  //原型对象不允许循环创建,如果是原型对象则抛异常
  if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
  }

  /**
  * BeanFactory也存在继承关系,如果当前BeanFactory中找不到BeanDefinition,则到parentBeanFactory容器中找,递归向上查找
  */
  BeanFactory parentBeanFactory = getParentBeanFactory();
  if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   String nameToLookup = originalBeanName(name);
   if (parentBeanFactory instanceof AbstractBeanFactory) {
    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
      nameToLookup, requiredType, args, typeCheckOnly);
   }
   else if (args != null) {
    return (T) parentBeanFactory.getBean(nameToLookup, args);
   }
   else if (requiredType != null) {
    return parentBeanFactory.getBean(nameToLookup, requiredType);
   }
   else {
    return (T) parentBeanFactory.getBean(nameToLookup);
   }
  }

  // typeCheckOnly=true表示调用这个方法只是做类型检查,不会去做真正对象创建,正常情况下typeCheckOnly=false
  if (!typeCheckOnly) {
   //如果不是仅仅做类型检测,而是需要创建bean实例,这里要将beanName放到alreadyCreated缓存,进行已创建标记
   markBeanAsCreated(beanName);
  }

  try {
   // 根据名字获取合并过的对应的RootBeanDefinition
   final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
   // 检查mbd是否为抽象的或mbd为单例,但存在args的情况(args只有初始化原型对象才允许存在)
   checkMergedBeanDefinition(mbd, beanName, args);

   /**
   * 拿到当前bean依赖的bean名称集合,如使用@DependsOn,在实例化自己之前,保证依赖的这些Bean全部被初始化,递归getBean
   */
   String[] dependsOn = mbd.getDependsOn();
   if (dependsOn != null) {
    for (String dep : dependsOn) {
     registerDependentBean(dep, beanName);
     // 先实例化@DependsOn中的bd
     getBean(dep);
    }
   }

   if (mbd.isSingleton()) {//创建单例Bean
    // 会先尝试从缓存中获取,获取失败就通过ObjectFactory的createBean方法创建
    sharedInstance = getSingleton(beanName, () -> {
     try {
      // 创建单例对象
      return createBean(beanName, mbd, args);
     }
     catch (BeansException ex) {
      destroySingleton(beanName);
      throw ex;
     }
    });
    //这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例。
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
   }
   else if (mbd.isPrototype()) {//创建多例Bean
    ...//省略    
   }
   else {//创建其它作用域的Bean
    ...//省略
   }
  }
  catch (BeansException ex) {
   cleanupAfterBeanCreationFailure(beanName);
   throw ex;
  }
 }

 // 检查是否为要求的类型,如果不是则尝试进行类型转换
 if (requiredType != null && !requiredType.isInstance(bean)) {
  ...//省略
 }
 return (T) bean;
}

createBean()

代码语言:javascript
复制
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
   throws BeanCreationException {

 ...//省略
        
 /**
 * 实例化前的处理,如果有实现InstantiationAwareBeanPostProcessor的BeanPostProcessor可以直接返回真正的bean实例
 * 然后依次所有注册的BeanPostProcessor的postProcessAfterInitialization方法(同样如果任意一次返回不为null,即终止调用。
 */
 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
 // 如果不为空,说明提前生成了实例,直接返回
 if (bean != null) {
  return bean;
 }

    ...//省略
        
 //创建Bean实例(一般真正创建Bean的方法)
 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
 return beanInstance;
}

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);这句代码比较关键,这里有个关键的扩展点回调:触发InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法执行。postProcessBeforeInstantiation()这个方法在创建Bean之前执行,可能会存在多个InstantiationAwareBeanPostProcessor,按照注册顺序一个个执行回调,如果其中有一个返回非null,则终止后续回调,然后直接调用BeanPostProcessor#postProcessAfterInitialization(Bean初始化完成回调接口),则表示整个Bean全部初始化完成,直接返回。依赖注入、init-method方法等都会被忽略执行。

如果InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation都返回null,则表示需要继续往下通过常规方式doCreateBean()方法创建Bean实例。

doCreateBean

代码语言:javascript
复制
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
   throws BeanCreationException {



  // Initialize the bean instance.
  // 开始对Bean实例进行初始化,依赖注入在这里发生,exposedObject 在初始化处理完后会返回作为依赖注入完成后的Bean
  Object exposedObject = bean;//这里还是原生对象
  try {
   /**

   populateBean(beanName, mbd, instanceWrapper);
   /**
    * 完成属性依赖注入后,进一步初始化Bean,具体进行了以下操作:
    *   1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
    *   2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
    *   3.如果实现了InitialzingBean,调用实现的 afterPropertiesSet()
    *   4.如果配置了init-mothod,调用相应的init方法
    *   5.遍历后置处理器,调用实现的postProcessAfterInitialization
    *
    * initializeBean方法执行bean的初始化方法
    * 经过AOP处理,原生对象转换成了代理对象
    * 执行后置处理器,aop就是在这里完成的处理
    */
   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<>(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.");
     }
    }
   }
  }

  // Register bean as disposable.
  try {
   // 如果实现了Disposable接口,会在这里进行注册,最后在销毁的时候调用相应的destroy方法
   registerDisposableBeanIfNecessary(beanName, bean, mbd);
  }
  catch (BeanDefinitionValidationException ex) {
   throw new BeanCreationException(
     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  }

  return exposedObject;
 }

doCreateBean是比较关键的一个方法,SpringdoXXX这种开头的基本都是真正干活的。这个方法完成的业务逻辑比较多,下面我们把这个方法拆解下分析。

createBeanInstance

createBeanInstance(beanName, mbd, args)这个方法是真正使用策略创建Bean实例,并返回包装类BeanWrapper,大部分情况就是调用无参构造方法通过反射创建对象,但是Spring要考虑各种情况,所以这个类设计的比较复杂。BeanWrapper是对创建的Bean进行了一层包装,主要是方便对Bean中各种属性进行操作。

MergedBeanDefinitionPostProcessor回调

执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition回调,这个扩展点主要用来解析注解信息,然后缓存起来供后续处理使用。比如:AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor等实现类都是在这个方法中把相应的注解信息解析缓存到集合中,比如@Autowired@Value@Resource,为后续实现依赖注入准备基础信息。

代码语言:javascript
复制
synchronized (mbd.postProcessingLock) {
 if (!mbd.postProcessed) {
  try {
   //获取所有实现MergedBeanDefinitionPostProcessor接口的后置处理器,调用其postProcessMergedBeanDefinition方法
   applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  }
  catch (Throwable ex) {
   throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     "Post-processing of merged bean definition failed", ex);
  }
  mbd.postProcessed = true;
 }
}

提前暴露Bean,防止循环依赖

这时的Bean刚被创建完成,但是还没有依赖注入、initMethod等方法初始化,把Bean包装到ObjectFactory中放到缓存Map中提前暴露出去,解决循环依赖问题。

代码语言:javascript
复制
// 提前将Bean暴露到IoC容器中,用于解决循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
 if (logger.isTraceEnabled()) {
  logger.trace("Eagerly caching bean '" + beanName +
    "' to allow for resolving potential circular references");
 }

 /**
 * 提前暴露beanName的ObjectFactory,用于解决循环引用,确保其他Bean能引用到此bean
 *
 * 其实就是调用singletonFactories.put(beanName, singletonFactory)将ObjectFactory存储到Map中
 *
 * A引用B,同时B也引用A
 * 1、在初始化A过程中执行到这里时,由于还没有初始化完成,所以会将A包装成一个ObjectFactory提前暴露出去;
 * 2、初始化A继续向下执行,当执行到populate进行依赖注入时,发现需要对象B,这时就getBean(B)递归进入到创建B的流程里面去了;
 * 3、B初始化过程中,也执行到了populate方法进行依赖注入时,需要getBean(A)获取对象A进行依赖注入;
 * 4、getBean(A)过程中首先getSingleton()从缓存中获取,getSingleton()就可以获取到提前暴露的A对应的ObjectFactory对象;
 * 5、然后调用ObjectFactory.getObject(),进而调用getEarlyBeanReference()
 * 6、getEarlyBeanReference()方法会触发一个扩展点:SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference如果返回非null,则可以覆盖当前bean
 */
 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

当存在循环依赖时,调用getEarlyBeanReference()获取依赖值时,主要注意这里面存在一个扩展点:SmartInstantiationAwareBeanPostProcessor

代码语言:javascript
复制
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
 Object exposedObject = bean;
 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
   if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
   }
  }
 }
 return exposedObject;
}

循环依赖情况下,注入还未完全初始化完成的Bean时,这时就会通过getEarlyBeanReference()获取依赖值。这时会调用SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference,如果有返回值则会覆盖掉之前初始化的Bean进行注入。

populateBean

populateBean方法完成依赖注入任务,主要包括三种方式的依赖注入:自动注入、注解注入和PropertyValues注入。

1、回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法,Bean创建之后,依赖注入之前执行,最后一次机会在属性注入前修改Bean的属性值,比如修改属性值、修改属性依赖的beanName等等。postProcessAfterInstantiation()方法有个boolean返回值,一般都是返回true;如果返回false,则表示不必继续进行依赖注入,立即停止后续的postProcessAfterInstantiation方法执行,并跳出populateBean方法执行。

代码语言:javascript
复制
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
  /**
  * InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation:Bean创建之后,依赖注入之前执行,最后一次机会在属性注入前修改Bean的属性值
  * postProcessAfterInstantiation()一般都是返回true,
  * 如果返回false,则表示不必继续进行依赖注入,立即停止后续的postProcessAfterInstantiation方法执行,并跳出populateBean方法执行。
  */
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
   if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    return;
   }
  }
 }
}

2、自动注入方式,该方式在实际开发中使用比较少,简单了解下即可,通过下面代码解析出自动注入所需的PropertyValues对象,最后执行applyPropertyValues(beanName, mbd, bw, pvs);完成依赖注入工作。

代码语言:javascript
复制
/**
* Spring内部可以对BeanDefinition进行设置值, 参照自定义的 BeanFactory中获取到BeanDefinition.getPropertyValue().addXXX();
* pvs是一个MutablePropertyValues实例,里面存储PropertyValue集合,通过PropertyValue实现对属性的赋值、依赖注入
*/
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

/**
*  自动注入方式:byName还是byType,依赖注入方式:如果设置了相关的依赖装配方式,会遍历Bean中的属性,根据类型或名称来完成相应注入,无需额外配置
*  @Autowired注解默认是AUTOWIRE_NO=0,即不走以下逻辑
*/
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
 // 深拷贝当前已有的配置
 MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
 // 自动根据名称注入
 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
  autowireByName(beanName, mbd, bw, newPvs);
 }
 // 自动根据类型注入
 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  autowireByType(beanName, mbd, bw, newPvs);
 }
 //组合需要依赖注入配置数据
 pvs = newPvs;
}

BeanDefinitionDefaultsautowireMode属性配置,BeanDefinition相关的全局配置都可以通过这个类设置:

代码语言:javascript
复制
public class BeanDefinitionDefaults {
 private Boolean lazyInit;
 private int autowireMode = AbstractBeanDefinition.AUTOWIRE_NO;
 private int dependencyCheck = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
 private String initMethodName;
 private String destroyMethodName;
}

ClassPathBeanDefinitionScanner#setBeanDefinitionDefaults可以配置该类,这样scanner扫描生成BeanDefinition时就会应用到该配置信息。

3、@Autowired@Value@Resource等注解方式实现的依赖注入;

代码语言:javascript
复制
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
 if (pvs == null) {
   pvs = mbd.getPropertyValues();
 }
 /**
 * 回调InstantiationAwareBeanPostProcessor#postProcessProperties方法
 * AutowiredAnnotationBeanPostProcessor,就是在这个方法中完成@Autowired、@Value注解的依赖注入
 * CommonAnnotationBeanPostProcessor:支持JSR-250的一些注解,如:@Resource、@PostConstruct、@PreDestroy等
 */
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
   PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
   if (pvsToUse == null) {
    if (filteredPds == null) {
     //获取出对象的所有set get方法,现在是有一个 getClass()方法,因为继承了Object, 没什么其他卵用
     filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    }
    //postProcessPropertyValues方法已废弃,被postProcessProperties替代
    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    if (pvsToUse == null) {
     return;
    }
   }
   pvs = pvsToUse;
  }
 }
}

注解方式实现的依赖注入主要借助于MergedBeanDefinitionPostProcessorInstantiationAwareBeanPostProcessor这两类扩展类实现。比如@Autowired@Value依赖注入的实现类是AutowiredAnnotationBeanPostProcessor,以及@Resource等JSR-250相关依赖注入的实实现类是CommonAnnotationBeanPostProcessor,他们都实现了MergedBeanDefinitionPostProcessorInstantiationAwareBeanPostProcessor这两个接口。一般是在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法中完成注解信息解析,然后缓存到Map等集合中,在InstantiationAwareBeanPostProcessor#postProcessProperties回调方法中,从缓存中查找依赖注入信息,然后进行依赖注入。

4、最后完成PropertyValues的依赖注入

代码语言:javascript
复制
if (pvs != null) {
 applyPropertyValues(beanName, mbd, bw, pvs);
}

PropertyValues的依赖注入主要有两个来源:一种就是上面自动注入解析出来的PropertyValue;另一种就是自己通过BeanDefinition#addPropertyValue方法设置,比如:

代码语言:javascript
复制
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(User.class);
//注入指定值
bdb.addPropertyValue("name", "张三");
//注入一个引用值,第二个参数指定beanName,依赖注入时从IoC查找到beanName对应的Bean进行注入
bdb.addPropertyReference("friend", "user03");
beanDefinitionRegistry.registerBeanDefinition("user", bdb.getBeanDefinition());

initializeBean

initializeBean()这个方法主要完成Bean的初始化工作,以及在初始化前后都存在BeanPostProcessor扩展点进行方法回调。

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
   invokeAwareMethods(beanName, bean);
   return null;
  }, getAccessControlContext());
 }
 else {
  /**
  * 如果实现了Aware接口,就对该bean进行一些设置。
  *  比如实现了BeanNameAware接口,那么对其bean的属性beanName上set上对应的beanName。
  *  如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂。
  */
  invokeAwareMethods(beanName, bean);
 }

 /**
 * 这里执行BeanPostProcessor#postProcessBeforeInitialization,因为马上就要执行init初始化工作
 * 这里会执行到InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization,
 * 这个方法中就实现了对Bean中@PostConstruct方法的调用
 */
 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 }

 try {
  //执行初始化方法init
  invokeInitMethods(beanName, wrappedBean, mbd);
 }
 catch (Throwable ex) {
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null),
    beanName, "Invocation of init method failed", ex);
 }
 if (mbd == null || !mbd.isSynthetic()) {
  /**
  * initMethod方法执行完成后,回调BeanPostProcessor#postProcessAfterInitialization方法
  * 
  * 执行Bean后置处理器初始化完成后after方法(aop增强就是在这里完成的)
  * AbstractAutoProxyCreator回调它的before()方法时,仅仅是标记哪些对象需要进行增强哪些对象不需增强,而没有立即生成代理对象
  * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):生成代理对象的逻辑就在这里面
  */
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }
 return wrappedBean;
}

这里注意点是存在三种方式触发initMethod:

  • @PostConstruct这种比较常用的注解方式,是在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization方法中被调用的,所以它执行时机是最早的;
  • 实现InitializingBean这种方式次之,具体见invokeInitMethods方法;
  • 最后执行的是@Bean(initMethod = "xxx")这种方式配置的initMethod
代码语言:javascript
复制
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
   throws Throwable {
 //实现InitializingBean,则调用afterPropertiesSet()方法
 boolean isInitializingBean = (bean instanceof InitializingBean);
 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
   ((InitializingBean) bean).afterPropertiesSet();
         ...//省略
 }
 /**
 * 执行BeanDefinition中设置到initMethodName的初始化方法,
 * 在ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod()方法中会解析@Bean注解上的initMethod设置进来
 */
 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);
  }
 }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Reactor2020 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • preInstantiateSingletons
  • doGetBean
  • createBean()
  • doCreateBean
    • createBeanInstance
      • MergedBeanDefinitionPostProcessor回调
        • 提前暴露Bean,防止循环依赖
          • populateBean
            • initializeBean
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档