Spring源码分析之Bean的创建过程详解(一)

简介: Spring源码分析之Bean的创建过程详解

前文传送门:

  1. Spring源码分析之预启动流程
  2. Spring源码分析之BeanFactory体系结构
  3. Spring源码分析之BeanFactoryPostProcessor调用过程详解

本文内容:

  1. 在IOC中,是如何通过beanDefition创建出一个bean的?
  2. 各BeanPostProcessor在这过程中扮演的角色,调用时机?

话不多说,直接正题走起,上图!

下面是bean创建过程的大致流程图,本文将以图中顺序进行逐步源码分析,小伙伴亦可与图中流程边对照边品食

原矢量图地址:https://www.processon.com/view/link/5f6174431e08531edf3134fb

我们知道,在Spring IOC前段部分有注册了一系列的BeanPostProcessor,在Bean的创建过程中,就将要使用到他们了,下面我给大家一一列出

  • AutowiredAnnotationBeanPostProcessor:在new AnnotatedBeanDefinitionReader时注册
  • CommonAnnotationBeanPostProcessor: 在new AnnotatedBeanDefinitionReader时注册
  • ApplicationContextAwareProcessor: 在prepareBeanFactory时注册
  • ApplicationListenerDetector: 在prepareBeanFactory时注册
  • ImportAwareBeanPostProcessor: 在配置类后置处理器调用postProcessBeanFactory注册
  • BeanPostProcessorChecker:在registerBeanPostProcessors时注册

以上就是Spring中内置的所有BeanPostProcessor了

同样,我们先从最开始的入口refresh开始分析

public void refresh(){
  //....省略前面部分
  // 实例化剩余的单例bean
  finishBeanFactoryInitialization(beanFactory);
}

finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
  // 将所有非懒加载的bean加载到容器中
  beanFactory.preInstantiateSingletons();
}

循环我们之前注册的所有beanDefinition,一个个的进行调用getBean注册到容器中

public void preInstantiateSingletons(){
  // 循环所有beanDefinition
  for (String beanName : beanNames) {
    // 将beanDefinition转化为RootBeanDefinition
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // 不是抽象类并且是单例并且非懒加载
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
      // 是否为工厂bean
      if (isFactoryBean(beanName)) {
        // 由于是以&开头获取bean,这里返回的是一个工厂bean,并且不会调用getObject方法
        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        if (bean instanceof FactoryBean) {
          // 判断是否要立即初始化bean
          FactoryBean<?> factory = (FactoryBean<?>) bean;
          boolean isEagerInit = (factory instanceof SmartFactoryBean &&
                           ((SmartFactoryBean<?>) factory).isEagerInit());
          if (isEagerInit) {
            // 以为&开头的方式再获取一次,此时会调用FactoryBean的getObject()方法
            getBean(beanName);
          }
        }
      }
      else {
        // 不是FactoryBean,直接使用getBean进行初始化
        getBean(beanName);
      }
    }
  }
}

接下来就是Spring的常规操作,调用do开头的doGetBean

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

以下为doGetBean中获取单例bean的逻辑

// 转化beanName 如果是以&开头则去除,如果有别名则获取别名
String beanName = transformedBeanName(name);
// 尝试从三级缓存中获取bean
Object sharedInstance = getSingleton(beanName);
// 是否从缓存中获取到了bean
if (sharedInstance != null && args == null) {
  // 如果是工厂类且name不以&开头,则调用工厂类的getObject()
  // 其他情况返回原对象
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

getSingleton

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从单例缓存池中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    // 获取不到,判断bean是否正在创建
    // 如果是正在创建,2种情况 1.多个线程在创建bean 2.发生循环依赖
    // 如果是多个线程,则由于同步锁阻塞于此
    // 循环依赖的问题较为复杂,将在下章详细分析
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
        // 从早期对象缓存池中获取
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
          // 从三级缓存中获取单例工厂
          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
          if (singletonFactory != null) {
            // 调用回调方法获取早期bean
            singletonObject = singletonFactory.getObject();
            // 将早期对象放到二级缓存,移除三级缓存
            this.earlySingletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
          }
        }
      }
    }
    return singletonObject;
  }

getObjectForBeanInstance

protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    // 判断name是否以&开头,是则直接返回该FactoryBean
    /*public static boolean isFactoryDereference(@Nullable String name) {
        return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
    }*/
    if (BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
    }
    // 不是工厂bean直接返回原对象
    if (!(beanInstance instanceof FactoryBean)) {
      return beanInstance;
    }
    // 尝试从缓存中获取,保证多次从工厂bean获取的bean是同一个bean
    object = getCachedObjectForFactoryBean(beanName);
    if (object == null) {
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      // 从FactoryBean获取对象
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
  }

getObjectFromFactoryBean的代码摘取片段

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess){
  // 获取bean,调用factoryBean的getObject()
  object = doGetObjectFromFactoryBean(factory, beanName);
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName){
  object = factory.getObject();
}

以上为从缓存中获取到bean,处理FactoryBean的逻辑,接下来我们看看实际创建bean的过程

以下为续接上面doGetBean中未从缓存中获取到bean的逻辑

// 如果有被@DependsOn标记,先创建DependsOn的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
  for (String dep : dependsOn) {
    registerDependentBean(dep, beanName);
    getBean(dep);
  }
}
// 单例bean
if (mbd.isSingleton()) {
  // 开始创建bean
  sharedInstance = getSingleton(beanName, () -> {
    // 真正创建bean
    return createBean(beanName, mbd, args);
  });
  // 如果是工厂类且name不以&开头,则调用工厂类的getObject()
  // 其他情况返回原对象
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

getSingleton,此方法为重载方法,与从缓存中获取bean并非同一个

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    // 开始创建bean时加锁,注意这个锁的同步对象与从缓存中获取时锁的同步对象相同
    synchronized (this.singletonObjects) {
      // 再次从缓存中获取,有直接返回,出现有的情况
      // 1.线程一正在创建A实例,线程二尝试获取,被同步锁阻塞
      // 2.线程一创建完毕,线程二进入同步代码块,从缓存中获取直接返回
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
        // 标记正在创建中
        beforeSingletonCreation(beanName);
        boolean newSingleton = false;
        try {
          // 调用回调函数获取到bean
          singletonObject = singletonFactory.getObject();
          newSingleton = true;
        }
        finally {
          // 清理状态
          afterSingletonCreation(beanName);
        }
        if (newSingleton) {
          // 将创建的bean添加到单例缓存池中,并移除二三级缓存
          addSingleton(beanName, singletonObject);
        }
      }
      return singletonObject;
    }
  }

createBean,终于开始创建bean了~

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // 第一次调用bean后置处理器,在bean实例化之前的进行处理
  // Spring内置的后置处理器中,无相关实现
  // 可使用自定义的后置处理器在这里进行中止bean的创建过程操作
  Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  if (bean != null) {
    // 如果自定义的后置处理器返回了bean,则直接return,bean的创建过程于此中断
    return bean;
  }
  // 进行创建bean
  Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // 实例化bean 第二次调用bean后置处理器,用于获取bean的有参构造器
  instanceWrapper = createBeanInstance(beanName, mbd, args);
  // 第三次 处理beanDefinition的元数据信息
  applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  // 是否允许暴露早期对象
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                    isSingletonCurrentlyInCreation(beanName));
  // 第四次 用于获取早期对象时的处理
  // 将获取早期对象的回调方法放到三级缓存中
  addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  // 第五、六次,填充属性 可使用的方式 byName byType @Resource @Value @Autowired @Inject
  populateBean(beanName, mbd, instanceWrapper);
  // 第七、八次,初始化
  exposedObject = initializeBean(beanName, exposedObject, mbd);
  // 第九次 判断bean是否有销毁方法,有则将bean注册到销毁集合中,用于容器关闭时使用
  registerDisposableBeanIfNecessary(beanName, bean, mbd);
  // 返回创建好的bean
  return exposedObject;
}

你以为这就结束了?

接下来我们就来看看这里后置处理器到底做了什么吧

由于第一次调用并未有任何处理,我们从第二次调用开始分析


目录
相关文章
|
1月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
3天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
3天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
39 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
这篇文章详细介绍了Spring框架中IOC容器的Bean管理,特别是基于XML配置方式的实现。文章涵盖了Bean的定义、属性注入、使用set方法和构造函数注入,以及如何注入不同类型的属性,包括null值、特殊字符和外部bean。此外,还探讨了内部bean的概念及其与外部bean的比较,并提供了相应的示例代码和测试结果。
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------5、IOC容器-Bean管理(三)
这篇文章深入探讨了Spring5框架中IOC容器的高级Bean管理,包括FactoryBean的使用、Bean作用域的设置、Bean生命周期的详细解释以及Bean后置处理器的实现和应用。
Spring5入门到实战------5、IOC容器-Bean管理(三)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
这篇文章是Spring5框架的实战教程,主题是IOC容器中Bean的集合属性注入,通过XML配置方式。文章详细讲解了如何在Spring中注入数组、List、Map和Set类型的集合属性,并提供了相应的XML配置示例和Java类定义。此外,还介绍了如何在集合中注入对象类型值,以及如何使用Spring的util命名空间来实现集合的复用。最后,通过测试代码和结果展示了注入效果。
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
这篇文章是Spring5框架的入门教程,详细讲解了IOC容器中Bean的自动装配机制,包括手动装配、`byName`和`byType`两种自动装配方式,并通过XML配置文件和Java代码示例展示了如何在Spring中实现自动装配。
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式
|
26天前
|
Java Spring
|
27天前
|
前端开发 Java 开发者