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

你以为这就结束了?

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

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


目录
相关文章
|
24天前
|
XML 安全 Java
|
1月前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
61 1
|
2天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
1天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
1天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
7天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
36 6
|
8天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
55 3
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
22天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
32 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
38 1