Spring中Bean的实例化详细流程

科技资讯 投稿 5900 0 评论

Spring中Bean的实例化详细流程

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

AbstractApplicationContext.refresh(

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

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

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

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的整个流程很清楚了。

@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的实例化详细流程

赞同 (22) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽