Spring源码分析のBean创建流程(上)
- 其他
- 2025-09-09 08:45:01

文章目录 前言一、preInstantiateSingletons1.1、getMergedLocalBeanDefinition1.2、isFactoryBean 二、getBean
前言
原生Spring在refresh方法中,会在finishBeanFactoryInitialization:preInstantiateSingletons方法中直接创建所有非懒加载的单例Bean。
一、preInstantiateSingletons
preInstantiateSingletons方法的主要逻辑:
遍历bean名称的集合。合并bean的定义 得到合并后的BeanDefinition。判断bean是否应该在此处被实例化。判断bean是否属于FactoryBean/SmartFactoryBean。进行实例化。实例化完成后,再次判断bean是否实现了SmartInitializingSingleton接口,如果实现了,则回调其中的afterSingletonsInstantiated方法。 @Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // 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) { //1.1 getMergedLocalBeanDefinition 合并bean的定义 得到合并后的BeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //进入该分支的条件 //1、Bean不是抽象的 //2、bean是单例 //3、bean不是懒加载 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //1.2 isFactoryBean 判断bean是否实现了FactoryBean接口 if (isFactoryBean(beanName)) { //如果实现了 就获取实现了FactoryBean接口的bean Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { //进行强转 将bean转换为接口FactoryBean的类型 FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; //这一块是判断bean实现的是否是SmartFactoryBean SmartFactoryBean 也是继承自 FactoryBean //只要满足条件,无论是if还是else都会回调SmartFactoryBean 的 isEagerInit 方法的逻辑 这里if分支只是额外加入了安全判断 if (System.getSecuritbeanyManager() != 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方法。 for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { StartupStep smartInitialize = this.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(); } } } 1.1、getMergedLocalBeanDefinitiongetMergedLocalBeanDefinition方法的作用是,得到合并后的bean定义。这里牵涉到Spring父子容器的概念:
public class Demo1 { public static void main(String[] args) { AnnotationConfigApplicationContext contextParent = new AnnotationConfigApplicationContext(AppConfigParent.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AppConfigParent.class); context.setParent(contextParent); context.refresh(); } }以上是在配置文件中关于父子容器的定义,假如在context中获取某个bean,而context中没有,就会去它的父容器中找。 而在Spring中,合并父子bean定义,主要的逻辑:
如果当前bean没有父类,则直接克隆当前的BeanDefinition,并使用它作为最终的合并结果。如果有父类,则递归调用getMergedLocalBeanDefinition去进行合并。 protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. //去合并后的bean定义缓存中找 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); //如果能找到就直接返回 if (mbd != null && !mbd.stale) { return mbd; } //否则进行合并 return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); } /** * 参数一 当前的bean名称 参数二 根据当前bean名称找到的对应的bean定义 */ protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { //加锁 防止重复合并 synchronized (this.mergedBeanDefinitions) { RootBeanDefinition mbd = null; RootBeanDefinition previous = null; // Check with full lock now in order to enforce the same merged instance. if (containingBd == null) { //再次尝试通过beanName 从 mergedBeanDefinitions 中获取RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); } //获取不到 就走合并的逻辑 if (mbd == null || mbd.stale) { previous = mbd; //如果当前bean名称找到的对应的bean定义 的 父beanName属性为null //说明可能两种情况 :1、当前bean定义就是RootBeanDefinition 2、当前bean定义不需要合并 if (bd.getParentName() == null) { // Use copy of given root bean definition. if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } //否则需要合并 else { // Child bean definition: needs to be merged with parent. BeanDefinition pbd; try { //对当前bean的父bean进行名称转换 String parentBeanName = transformedBeanName(bd.getParentName()); //当前bean名称和父bean名称不相同 if (!beanName.equals(parentBeanName)) { //递归合并 因为当前bean 的 父bean有可能还有父bean pbd = getMergedBeanDefinition(parentBeanName); } //当前bean名称和父bean名称相同 else { //获取父 BeanFactory BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { // 从父工厂中获取合并后的父类 BeanDefinition pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without a ConfigurableBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } // Deep copy with overridden values. //创建一个新的 RootBeanDefinition,基于父类 BeanDefinition mbd = new RootBeanDefinition(pbd); //当前的bd覆盖父类的属性 mbd.overrideFrom(bd); } // Set default singleton scope, if not configured before. //如果没有设置作用域 默认是单例的 if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(SCOPE_SINGLETON); } // A bean contained in a non-singleton bean cannot be a singleton itself. // Let's correct this on the fly here, since this might be the result of // parent-child merging for the outer bean, in which case the original inner bean // definition will not have inherited the merged outer bean's singleton status. if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // Cache the merged bean definition for the time being // (it might still get re-merged later on in order to pick up metadata changes) //进行缓存 if (containingBd == null && isCacheBeanMetadata()) { this.mergedBeanDefinitions.put(beanName, mbd); } } if (previous != null) { copyRelevantMergedBeanDefinitionCaches(previous, mbd); } //返回合并后的定义 return mbd; } } 1.2、isFactoryBeanisFactoryBean主要用于判断当前的bean是否实现了FactoryBean接口,如果某个类实现了FactoryBean接口,则会产生两个实例,第一个是实现了FactoryBean接口的bean的本身,第二个是其中getObject()方法返回的实例。默认的getBean(),得到的是getObject()方法返回的实例。如果要获取实现了FactoryBean接口的bean的本身,则需要getBean()时在名称前加上"&"符号。
@Override public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException { //这里获取到的是实现了`FactoryBean`接口的bean的本身 String beanName = transformedBeanName(name); //尝试从单例池中获取 Object beanInstance = getSingleton(beanName, false); //如果获取到了,就判断是否实现了FactoryBean if (beanInstance != null) { return (beanInstance instanceof FactoryBean); } // 判断是否要从父容器中获取 if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) { // No bean definition found in this factory -> delegate to parent. return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name); } //这里也会走bean定义合并 return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName)); } /** * 这里的isFactoryBean属性作为一个缓存的效果,后续直接取该类bean定义的该属性的值即可。 * */ protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) { //尝试从合并后的bean定义中 获取isFactoryBean属性 Boolean result = mbd.isFactoryBean; //获取不到 if (result == null) { //判断当前bean是否实现了FactoryBean接口 Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class); result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType)); //并且将isFactoryBean属性设置值。 mbd.isFactoryBean = result; } return result; } 二、getBeangetBean是Spring创建所有非懒加载单例bean的方法,总体的逻辑,如果容器中已经有了目标bean,就直接返回,否则就去创建。 该方法有以下的情况:
单例池中能获取到,走实例化 bean 的逻辑。单例池中没有,Bean 父工厂不为空并且在 Bean 定义中不存在该 BeanName,委托给父工厂。父工厂会尝试获取该 Bean,如果父工厂也没有,则继续查找。单例池中没有,Bean 父工厂为空并且在 Bean 定义中存在该 BeanName,则进行 Bean 定义合并。合并时,父 Bean 定义会被合并到当前 Bean 定义中,最终生成 Bean 实例。根据 Bean 的作用域执行不同操作: 单例 Bean:创建后加入单例缓存池,后续请求直接返回缓存中的实例。原型 Bean:每次请求创建新的实例,不缓存。其他作用域:根据配置的作用域(如 request、session 等)执行对应的实例化和管理逻辑。 循环依赖的处理:Spring 会通过提前暴露实例来解决 单例 Bean 的循环依赖问题,原型 Bean 则无法解决循环依赖。初始化和销毁:Spring 会在容器启动时初始化单例 Bean,并处理 Bean 的初始化和销毁方法。 protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { //对bean的名称进行转换 这里会去除beanName中的& String beanName = transformedBeanName(name); Object beanInstance; // Eagerly check singleton cache for manually registered singletons. //尝试从单例池中获取bean Object sharedInstance = getSingleton(beanName); //单例池中能获取到 if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } //实例化bean beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } //单例池中没有 说明是第一次获取 else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. //判断是否存在循环依赖的问题 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. //得到bean工厂 BeanFactory parentBeanFactory = getParentBeanFactory(); //bean工厂不为空 并且在bean定义中不存在该beanName if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. //如果传入的name中,有&字符串,则在此处重新加上&字符串 String nameToLookup = originalBeanName(name); // 如果父工厂是 AbstractBeanFactory 类型 if (parentBeanFactory instanceof AbstractBeanFactory) { // 委托给父工厂执行 doGetBean 方法,查找并返回 Bean 实例 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } // 如果传入了构造参数 args else if (args != null) { // 委托给父工厂并传递构造参数来获取 Bean 实例 return (T) parentBeanFactory.getBean(nameToLookup, args); } // 如果指定了 requiredType 类型 else if (requiredType != null) { // 委托给父工厂的标准 getBean 方法 return parentBeanFactory.getBean(nameToLookup, requiredType); } else { // 委托给父工厂的标准 getBean 方法,返回该 Bean return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") .tag("beanName", name); try { if (requiredType != null) { beanCreation.tag("beanType", requiredType::toString); } //进行bean定义合并 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //如果bean定义是抽象的,则抛出异常 checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. //找到该bean定义的DependsOn属性。 //@DependsOn注解,用于标记在创建该bean时,应该先创建该bean依赖的某个bean String[] dependsOn = mbd.getDependsOn(); //如果存在依赖的bean if (dependsOn != null) { for (String dep : dependsOn) { //这里是对于循环依赖的判断 即当前bean所依赖的bean,又依赖了当前bean //这种情况等价于 构造方法的循环依赖 无解 所以直接抛出异常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } //注册bean的依赖关系 registerDependentBean(dep, beanName); try { //先去创建当前bean所依赖的bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 下面这一段的逻辑 根据bean不同的作用域 执行不同的操作 单例bean就直接创建 并加入单例池 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //原型bean会创建 不会被缓存 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } //其他的作用域,走自己的初始化逻辑 else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean '" + beanName + "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } } } catch (BeansException ex) { beanCreation.tag("exception", ex.getClass().toString()); beanCreation.tag("message", String.valueOf(ex.getMessage())); cleanupAfterBeanCreationFailure(beanName); throw ex; } finally { beanCreation.end(); } } return adaptBeanInstance(name, beanInstance, requiredType); }其中bean的依赖关系,是存放在DefaultSingletonBeanRegistry的成员变量中: dependentBeanMap: 当前bean被哪些bean依赖;dependenciesForBeanMap:当前bean依赖了哪些bean 然后会调用createBean方法完成bean的创建。
Spring源码分析のBean创建流程(上)由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Spring源码分析のBean创建流程(上)”