Spring中Bean的实例化详细流程

这篇具有很好参考价值的文章主要介绍了Spring中Bean的实例化详细流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

还是举个例子,我有一个朋友小汪他远赴南方某城市打工。然后安定下来后他的朋友很想来家里玩,但是呢我这个朋友家里搞的很乱,所以他不好意思请朋友来家里玩。这时我的另一个朋友说那请一个保姆把家里好好整理一下就可以了,然后给他介绍了一个保姆大S(PS:本文无意指向任何人,因为Spring的前缀是S)然后就把家里整理得井井有条,就请朋友来家里玩了。

好了引入正文,很早很早的Java开发者应该熟悉,最早的时候我们前端访问后端都是需要自己写Servlet的,大概是一个接口写一个Servlet。Java开发又是面向对象的编程,我们程序里面写了new 了很多的对象。写了很多个Servlet,对象很难管理造成我们的程序很乱,都看不下去。后面Spring来了对象都交给了Spring管理,Servlet相关的也都交给了SpringMVC,这样我们开发就顺利多了。好了这下懂我上面举的例子了吧,懂得保姆是什么意思了吧【Spring就像一个管家,一个保姆】。所以多了解Spring相关知识我们提高开发效率有很大的帮助。既然我们的对象交给了Spring管理,那我们的对象怎么生成的呢,就让我们一起看下。

Spring中Bean的实例化详细流程

我们在使用Spring的时候,容器中的Bean在我们项目启动的时候都已经给我们生成了,直接使用就行了。容器启动的时候会调用这个方法:

AbstractApplicationContext.refresh()

然后就会调用下面这个方法:

// Instantiate all remaining (non-lazy-init) singletons.
 // 翻译一下就是 实例化所有非懒加载的Bean
finishBeanFactoryInitialization(beanFactory);

如图refresh中的方法,它再次调用的每个方法都很重要,实例化所有单例Bean的方法在这个方法的最后调用

Spring中Bean的实例化详细流程

我们写的对象基本都在这个方法内进行实例化。【PS方法只讲一些很重要的,具体的更详细方法调用我会在文章后面的流程图中展示出来。】

DefaultListableBeanFactory.preInstantiateSingletons()。
@Override
 public void preInstantiateSingletons() throws BeansException {

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    // 获取所有的要实例化的Bean的名称
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singleton beans...
    // 开始初始化单例的Bean
    for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
       // Bean 不是抽象的,是单例的,不是懒加载的进入如下分支
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        // 如果是FactoryBean进入此分支。本次只聊自己开发写的非FactoryBean
        // 所以聊else下面的分支。
        if (isFactoryBean(beanName)) {
        // FactoryBean的名称很特别
          Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
          if (bean instanceof FactoryBean) {
            final FactoryBean<?> factory = (FactoryBean<?>) bean;
            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);
        }
      }
    }
  }

然后会进入如下方法。

AbstractBeanFactory.doGetBean() 的方法。
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    //  这个方法主要是获取Bean的名称,一些Bean的名称可能命名的比较特别
    // 需要进行转换。
    final String beanName = transformedBeanName(name);
    Object bean;
    // Eagerly check singleton cache for manually registered singletons.
    // 首先先从容器的缓存中获取Bean,如果容器中已经存在,直接返回。
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } 
    else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      // 先检查这个Bean是否在创建中,如果在创建中抛出异常 
      if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
      }
       // 标记Bean为正在创建中。
      if (!typeCheckOnly) {
        markBeanAsCreated(beanName);
      }
      try {
        // Create bean instance.
        //  如果Bean是单例开始创建Bean .
        //  后面判断还有Prototype(多例)不是要讲的重点,代码删除了。
        if (mbd.isSingleton()) {
        //  这个方法是Java 8的 lambda 写法,这个方法里面会把创建好的
        // Bean放到Spring容器中,后面再获取这个Bean直接从容器中获取了。
          sharedInstance = getSingleton(beanName, () -> {
            try {
            // 正式开始创建Bean 。
              return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
            // 创建过程出现异常,销毁Bean
              destroySingleton(beanName);
              throw ex;
            }
          });
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
    return (T) bean;
  }

然后是正式真正的创建Bean的方法如下:

AbstractAutowireCapableBeanFactory.createBean() 的方法。
@Override
  protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    try {
     // doCreateBean 是Spring正在做事的方法。
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  }
  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    // Instantiate the bean.
    //  实例化Bean 先创建一个BeanWrapper .这个方法里面Spring 一般为默认
    // 无参的构造方法创建对象,所以大家如果重写对象的构造方法的时候,一定
    // 要把无参构造方法也写出来。要不然某些情况下启动Spring容器可能会报错。
    if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
    // 为Bean的属性赋值。
      populateBean(beanName, mbd, instanceWrapper);
      // 初始化Bean 。
      exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    return exposedObject;
  }
  // 初始化Bean。
  protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 如果你的Bean实现了Spring内置的Aware方法,会在这里执行
    invokeAwareMethods(beanName, bean);
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
    // 执行Bean的初始化前置处理器,很重要也就是Spring的钩子函数
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
    // 执行Bean的初始化方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    if (mbd == null || !mbd.isSynthetic()) {
    // 执行Bean的后置处理器,也很重要。
    // 很多写底层架构的人都会对此钩子方法灵活应用
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
  }

PS:下面是Bean实例化的详细的流程图,由于画好后的整个流程图无法完全保存,只有一张一张的截屏了。图片一张一张往下看就是整个完整的流程,自己可以找着图片一步一步看,就会对Bean的整个流程很清楚了。

Spring中Bean的实例化详细流程

Spring中Bean的实例化详细流程

Spring中Bean的实例化详细流程

读完熟悉了Spring实例化的流程你能做些什么呢?

Spring中Bean的实例化详细流程

1:比如实现BeanPostProcessor。A初始化前和后分别会执行下面2个方法。

@Component
public class A implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName);
        return null;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName);
        return null;
    }
}

2:实现InitializingBeanA初始化的时候会执行以下方法。

@Component
public class A implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行InitializingBean的afterPropertiesSet方法");
    }
}

上面实现的方法都会在A实例化的时候执行,如果你写的业务逻辑有需要在A实例化时候执行的就可以使用上面的方法完成。

Spring中Bean的实例化详细流程

 

欢迎跟着图中走一遍源码,相信你会对Spring创建Bean的流程更加了解。看一些源码你的思路会更清晰,写代码也更得心应手,写代码的时候你可能不自己觉的就按照这些大神写代码的思路去完成高质量的代码。文章来源地址https://www.toymoban.com/news/detail-411312.html

到了这里,关于Spring中Bean的实例化详细流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Bean的实例化过程

    一、前言 对于写Java的程序员来说,Spring已经成为了目前最流行的第三方开源框架之一,在我们充分享受Spring IOC容器带来的红利的同时,我们也应该考虑一下Spring这个大工厂是如何将一个个的Bean生产出来的,本期我们就一起来讨论一下Spring中Bean的实例化过程。 1.1 Spring Bean

    2024年02月10日
    浏览(45)
  • 【Spring】使用@Bean和@Import注解配置Bean,与Bean的实例化

    目录 1、bean是什么 2、配置bean 2.1、使用@Bean注解配置Bean 2.2、使用@Import注解配置Bean  3、实例化Bean         在 Spring 中,Bean 是指由 Spring 容器管理的对象。Spring IOC 容器负责创建、配置和管理这些 Bean 对象的生命周期。Spring IOC 容器会管理应用程序中的组件,并通过依赖注

    2024年04月15日
    浏览(34)
  • spring实例化bean之循环依赖

    serviceA里注入了serviceB,serviceB里又注入了serviceA,这样在实例化serviceA时,在doCreateBean时的populateBean时会先实例化serviceB,然后实例化serviceB,在serviceB的doCreateBean方法的populateBean又会去找servcieA,这样循环依赖就产生了。 解决办法就是在populateBean之前把当前的serviceA提前暴露,然

    2024年02月08日
    浏览(44)
  • 【Spring(四)】万字详解bean的实例化

      在上篇文章,我们已经完成了 入门案例 的学习,在入门案例中,我们讲了三块东西,首先是 bean怎么定义配置,DI怎么去制作配置以及我们的容器对象如何去获取 在接下来的内容中,我们将针对以上三块东西展开学习✍️✍️。 在学习bean的实例化之前,我们先来学习 b

    2024年02月21日
    浏览(37)
  • Spring中Bean加载流程

    BeanDefinition 1.1什么是BeanDefinition? 1.2 BeanDifinition中重要的属性 1.3 BeanDefinition的解析 BeanFactory 2.1 什么是BeanFactory? 2.2 BeanFactory工作流程: Bean生命周期 3.1 什么是Bean生命周期? Bean生命周期是Spring中一个Bean创建过程和销毁过程中所经历的步骤,其中Bean创建过程是重点。 3.2 核

    2024年02月09日
    浏览(37)
  • 【Spark】一个例子带你了解Spark运算流程

    写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成,愿将昔日所获与大家交流一二

    2024年02月11日
    浏览(42)
  • spring中bean实例化的三种方式 -- Spring入门(二)

    为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。 (博客的参考源码以及可以在我主页的资源里找到,如果在学

    2024年02月16日
    浏览(43)
  • 【Spring篇】讲解Bean的三种配置和实例化方法

    🎊专栏【Spring】 🍔喜欢的诗句:天行健,君子以自强不息。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 在Spring框架中,Bean的配置和实例化是很重要的基础内容。掌握各种配置方式,才能灵活管理Bean对象。本文将全面介绍Bean的别名配置、作用范围配置,以及

    2024年02月08日
    浏览(52)
  • Spring源码笔记之SpringIOC--(2)从BeanDefinition到Bean实例

    从BeanDefinition到Bean实例 对比 SimpleBeanDefinitionRegistry 和 DefaultListableBeanFactory 的源码,中间省略一些无关紧要的逻辑: SimpleBeanDefinitionRegistry.java DefaultListableBeanFactory.java 从类关系上来看 DefaultListableBeanFactory 不单单实现了 BeanDefinitionRegistry ,还实现了 BeanFactory (继承了 AbstractA

    2024年02月19日
    浏览(42)
  • Bean 作用域、生命周期和Spring执行流程

    假设现在有⼀个公共的 Bean,提供给 A ⽤户和 B ⽤户使⽤,然⽽在使⽤的途中 A ⽤户却“悄悄”地修改了公共 Bean 的数据,导致 B ⽤户在使⽤时发⽣了预期之外的逻辑错误。 我们可以看到,B 用户在使用这个Bean对象时,得到的Dog是被A 用户修改过的,这无疑会给 B 用户带来很

    2024年02月12日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包