前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring系列三之Bean实例化流程

Spring系列三之Bean实例化流程

原创
作者头像
用户9511949
发布2024-09-05 20:03:52
1450
发布2024-09-05 20:03:52

1 Bean实例化

紧接着上文,Spring的Bean实例化发生在刷新IOC容器阶段的倒数第二步finishBeanFactoryInitialization(beanFactory),最终在该方法中调用DefaultListable.preInstantiateSingletons()方法实例化所有非懒加载的Bean实例,代码如下

代码语言:javascript
复制
public void preInstantiateSingletons() throws BeansException {
    ......
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 加载所有非懒加载的Bean
    for (String beanName : beanNames) {
       RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          if (isFactoryBean(beanName)) {
             Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
             if (bean instanceof FactoryBean) {
                // 如果是FactoryBean,先判断是不是需要在此处实例化,需要才实例化
                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 {
             getBean(beanName);
          }
       }
    }

    // 所有非懒加载Bean实例加载完成之后,Bean如果实现了SmartInitializingSingleton,调用其回调方法
    // afterSingletonsInstantiated(),这个特性在xxl-job执行器的初始化中有使用过
    for (String beanName : beanNames) {
       Object singletonInstance = getSingleton(beanName);
       if (singletonInstance instanceof SmartInitializingSingleton) {
          StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
                .tag("beanName", beanName);
          SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
          if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                smartSingleton.afterSingletonsInstantiated();
                return null;
             }, getAccessControlContext());
          }
          else {
             smartSingleton.afterSingletonsInstantiated();
          }
          smartInitialize.end();
       }
    }
}

代码也比较清晰,第一步实例化所有非懒加载的实例,其核心就是调用getBean(beanName)方法,第二步如果Bean实现了SmartInitializingSingleton接口,调用其回调方法afterSingletonsInstantiated(),而getBean方法是调用AbstractBeanFactory.doGetBean方法,doGetBean方法的代码比较复杂,以一个循环依赖且是单例模式的例子来梳理代码的流程(A依赖B,B依赖A,A,B都是单例模式),如下只保留了核心代码的流程

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

    String beanName = transformedBeanName(name);
    Object beanInstance;
   
    // 第一步,先从缓存中获取Bean实例
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
       ......
       beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
       ......
       StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
             .tag("beanName", name);
       try {
          ......
          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
          checkMergedBeanDefinition(mbd, beanName, args);

          // 第二步,检查Bean依赖
          String[] dependsOn = mbd.getDependsOn();
          if (dependsOn != null) {
             for (String dep : dependsOn) {
                if (isDependent(beanName, dep)) {
                   throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                         "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                }
                registerDependentBean(dep, beanName);
                try {
                   getBean(dep);
                }
                catch (NoSuchBeanDefinitionException ex) {
                   throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                         "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
             }
          }
          // 第三步,创建Bean
          if (mbd.isSingleton()) {
             sharedInstance = getSingleton(beanName, () -> {
                try {
                   return createBean(beanName, mbd, args);
                } catch (BeansException ex) {
                   destroySingleton(beanName);
                   throw ex;
                }
             });
             beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
          } else if (mbd.isPrototype()) {
             ......
          } else {
             ......
          }
       } catch (BeansException ex) {
          ......
       } finally {
          beanCreation.end();
       }
    }
    return adaptBeanInstance(name, beanInstance, requiredType);
}

下面就一步一步来分析

第一步:首先调用getSingleton(beanName)从缓存中获取A实例,如下

代码语言:javascript
复制
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
       singletonObject = this.earlySingletonObjects.get(beanName);
       if (singletonObject == null && allowEarlyReference) {
          synchronized (this.singletonObjects) {
             // Consistent creation of early reference within full singleton lock
             singletonObject = this.singletonObjects.get(beanName);
             if (singletonObject == null) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null) {
                   ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                   if (singletonFactory != null) {
                      singletonObject = singletonFactory.getObject();
                      this.earlySingletonObjects.put(beanName, singletonObject);
                      this.singletonFactories.remove(beanName);
                   }
                }
             }
          }
       }
    }
    return singletonObject;
}

从上面的代码中可以看出,Spring用了三级缓存来处理

第一级缓存singletonObjects,是一个Map<String, Object>结构,key是BeanName,value是Instance,先从singletonObjects中获取实例,如果实例不为空,直接返回,所以这里先实例化A的时候,A为空且不在创建当中(创建中的实例用singletonsCurrentlyInCreation这个Set结构来保存),直接返回null

第二步:检查依赖,第一步返回null,则走到创建Bean的流程,创建Bean之前,首先要检查Bean依赖于哪些Bean,这里的依赖并不是指@Autowired这类属性注入的依赖关系,而是@DependsOn这类注解配置的依赖,如果有依赖,则先实例化DependsOn的Bean,如果没有就开始第三步创建Bean

第三步:创建Bean,调用了getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,代码如下

代码语言:javascript
复制
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    ......
    synchronized (this.singletonObjects) {
       // 还是先从第一级缓存singletonObjects中获取实例,不为null直接返回
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null) {
          // 在创建的过程当中,如果Bean正处于销毁中,则抛出异常
          if (this.singletonsCurrentlyInDestruction) {
             throw new BeanCreationNotAllowedException(beanName,
                   "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                   "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
          }
          ......
          // 执行创建之前的操作,其实就是将该Bean标记为创建中的状态,也就是将BeanName放入到上面提到过的
          // singletonsCurrentlyInCreation这个Set结构中
          beforeSingletonCreation(beanName);
          boolean newSingleton = false;
          boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
          if (recordSuppressedExceptions) {
             this.suppressedExceptions = new LinkedHashSet<>();
          }
          try {
             // 通过singletonFactory创建Bean
             singletonObject = singletonFactory.getObject();
             newSingleton = true;
          }
          catch (IllegalStateException ex) {
             ......
          } catch (BeanCreationException ex) {
             ......
          } finally {
             ......
             // 执行创建之后的操作,即将BeanName从singletonsCurrentlyInCreation这个Set结构中删除
             afterSingletonCreation(beanName);
          }
          if (newSingleton) {
             // 将生成的Bean放入到第一级缓存singletonObjects当中,并且删除第二级和第三级缓存
             addSingleton(beanName, singletonObject);
          }
       }
       return singletonObject;
    }
}

说明都放在了上面的代码注释中,下面再来看看singletonFactory创建Bean的过程,是通过调用createBean(beanName, mbd, args)方法创建,代码如下

代码语言:javascript
复制
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
       throws BeanCreationException {
    ......
    RootBeanDefinition mbdToUse = mbd;
    ......
    try {
       // 执行Bean实例化之前的操作,即依次执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
       Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
       // 如果在postProcessBeforeInstantiation方法中返回了实例,直接返回
       if (bean != null) {
          return bean;
       }
    } catch (Throwable ex) {
       ......
    }
    try {
       // 创建实例
       Object beanInstance = doCreateBean(beanName, mbdToUse, args);
       if (logger.isTraceEnabled()) {
          logger.trace("Finished creating instance of bean '" + beanName + "'");
       }
       return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
       ......
    } catch (Throwable ex) {
       ......
    }
}

从上面的代码中可以看出createBean的方法比较简单,就是在创建实例之前先依次执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,然后再调用doCreateBean(beanName, mbdToUse, args)方法创建实例,看看doCreateBean方法

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

    // 1.实例化bean.
    BeanWrapper instanceWrapper = null;
    ......
    if (instanceWrapper == null) {
       instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    ......

    // 2.封装一个Bean创建工厂放入第三级缓存singletonFactories
    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");
       }
       addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    Object exposedObject = bean;
    try {
       // 3.设置Bean属性
       populateBean(beanName, mbd, instanceWrapper);
       // 4.初始化Bean
       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);
       }
    }
    // 5.设置exposedObject 
    if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
		    ......
		}
	}
    return exposedObject;
}

doCreateBean方法的逻辑也比较清晰,主要有以下的步骤,依次来看看

1.实例化bean,这一步没啥好说的,主要就是创建一个Bean实例

2.如果允许循环依赖并且是在创建中的状态,就封装一个Bean创建工厂放入第三级缓存singletonFactories,singletonFactories也是一个Map结构,这个创建工厂并不是创建Bean的实例(第一步已经做了),而是在第一步创建的Bean的基础上做一层或者多层封装

3.设置Bean属性,主要通过populateBean(beanName, mbd, instanceWrapper)方法来执行,代码如下

代码语言:javascript
复制
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    ......
    // 首先执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
    // 即在Bean实例化之后需要执行的方法
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
       for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
          if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
             return;
          }
       }
    }

    ......

    // 再次执行InstantiationAwareBeanPostProcessor的各种后置处理方法
    // @AutoWire注解就是在此处通过AutowiredAnnotationBeanPostProcessor这个类处理的
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
       if (pvs == null) {
          pvs = mbd.getPropertyValues();
       }
       for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
          PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
          if (pvsToUse == null) {
             if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
             }
             pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
             if (pvsToUse == null) {
                return;
             }
          }
          pvs = pvsToUse;
       }
    }
    ......
}

由于A依赖B,所以在populateBean方法中又会重新调用doGetBean方法获取B的实例,在B实例的实例化过程中同样的逻辑重新执行一遍又到populateBean方法,由于B又依赖于A,所以在populateBean方法中又会去获取A实例,所有这里我们再来看看getSingleton(beanName,true)方法,如下

代码语言:javascript
复制
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
       singletonObject = this.earlySingletonObjects.get(beanName);
       if (singletonObject == null && allowEarlyReference) {
          synchronized (this.singletonObjects) {
             // Consistent creation of early reference within full singleton lock
             singletonObject = this.singletonObjects.get(beanName);
             if (singletonObject == null) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null) {
                   ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                   if (singletonFactory != null) {
                      singletonObject = singletonFactory.getObject();
                      this.earlySingletonObjects.put(beanName, singletonObject);
                      this.singletonFactories.remove(beanName);
                   }
                }
             }
          }
       }
    }
    return singletonObject;
}

这里和第一次获取A的逻辑不同,这依次会走到第三级缓存singletonFactories这里,通过之前创建的工厂来生成A的实例,即通过getEarlyBeanReference(beanName, mbd, bean)方法来生成最终的A实例,如下

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

这里就不得不提到AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor了,如果我们的类有切面,就是通过AnnotationAwareAspectJAutoProxyCreator来生成的代理类,这样最终A的实例就生成了,最后再将A的创建工厂从第三级缓存singletonFactories中删除,再放入到第二级缓存earlySingletonObjects中,这样就完成了B实例中的A的依赖注入

4.初始化Bean

最后一步通过initializeBean(beanName, exposedObject, mbd)方法进行初始化,如下

代码语言:javascript
复制
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 执行各种Aware接口的注入,这一步处理的Aware主要有BeanNameAware、BeanClassLoaderAware、
    // BeanFactoryAware
    if (System.getSecurityManager() != null) {
       AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
          invokeAwareMethods(beanName, bean);
          return null;
       }, getAccessControlContext());
    }
    else {
       invokeAwareMethods(beanName, bean);
    }
    // 执行BeanPostProcessor的postProcessBeforeInitialization方法
    // 即在初始化之前要执行的方法
    // 其中像@PostConstruct注解的方法就是在此处执行
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
       wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
       // 执行初始化的方法,先执行InitializingBean的接口方法afterPropertiesSet,再执行配置的init方法
       invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
       throw new BeanCreationException(
             (mbd != null ? mbd.getResourceDescription() : null),
             beanName, "Invocation of init method failed", ex);
    }
    // 执行BeanPostProcessor的postProcessAfterInitialization
    // 即在初始化之后要执行的方法
    // 如果有切面,生成代理类也是在这个步骤处理
    if (mbd == null || !mbd.isSynthetic()) {
       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

初始化完了之后,将BeanName从singletonsCurrentlyInCreation这个Set结构中删除,再将生成的Bean放入到第一级缓存singletonObjects当中,并且删除第二级和第三级缓存,这样B的实例就生成好了,B生成好了之后又回到A的populateBean方法就完成了A实例中的B的依赖注入

5.设置exposedObject

在B通过initializeBean方法完成初始化后返回的wrappedBean,如果有切面的话,其实返回的是代理对象,但是A对象的代理对象已经在B的实例化过程当中放到了earlySingletonObjects中,那么A在执行initializeBean方法时就不应该再去重新生成一个代理对象,而是应该从earlySingletonObjects中去取,然后直接赋值给exposedObject即可,这一步非常重要,不然会导致B中引用的A对象和singletonObjects中的A对象不是同一个对象,代码如下

代码语言:javascript
复制
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
       Object cacheKey = getCacheKey(bean.getClass(), beanName);
       if (this.earlyProxyReferences.remove(cacheKey) != bean) {
          return wrapIfNecessary(bean, beanName, cacheKey);
       }
    }
    return bean;AnnotationAwareAspectJAutoProxyCreator
}

在initializeBean方法中的applyBeanPostProcessorsAfterInitialization方法中会调用AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator的postProcessAfterInitialization方法,在此方法中如果earlyProxyReferences中包含了该Bean,说明已经通过getEarlyBeanReference方法生成了代理类,这里就不会再执行wrapIfNecessary方法

文末尾记录一个常见的面试题,为什么Spring解决循环依赖是三级缓存,而不是二级缓存?

个人理解:二级缓存也能解决问题,但是要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理(因为在Spring中如果有AOP,注入的都是代理对象)这样违背了Spring设计的原则,Spring在设计的时候就是使用AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor在initializeBean的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理,只有当确实有循环依赖时,才会提前生成代理对象

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

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