Spring Ioc源码解析:Bean实例化流程详解是怎样的?

2026-05-25 06:291阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1584个文字,预计阅读时间需要7分钟。

Spring Ioc源码解析:Bean实例化流程详解是怎样的?

Spring Ioc 源码解析系列--Bean 实例化过程(一)前言+上一篇文章Spring Ioc 源码解析系列--IoC 容器注册BeanPostProcessor处理器以及事件消息处理器已完成,对IoC容器启动方法refresh()也进行了解析。

Spring Ioc源码分析系列--Bean实例化过程(一) 前言

上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对IoC容器启动方法也就是refresh()方法的简单分析。但是之前的分析在对容器实例化Bean的过程的略过了,留到了这后续的文章分析,所以这篇文章会对Bean的实例化过程做一个介绍。

首先来理一下本文的思路:关键词是实例化。由于Spring是利用反射实现的实例化,脑子里先简单想一下Java里利用发射实例化一个对象需要哪些步骤和操作。毫无疑问,我们首先要知道对象的class,接着需要确定使用什么构造函数以及确定构造函数的参数等。利用这些已经基本可以实现一个对象的实例化,当然实际上需要的东西可能更多更复杂,这里只是举个例子。那么需要的这些信息可以去哪里提取呢?对Spring有了解的可能都马上能想到BeanDefinition,这是一份原料表,里面有我们构造一个实例化对象所需的所有参数。如果不太理解这个定义,可以参考一下上篇文章的例子。

如果不清楚BeanDefinition是从哪里来的以及不清楚如何定义的,可以参考之前的文章Spring Ioc源码分析系列--Ioc源码入口分析的关键实现系列方法 loadBeanDefinitions ()。这篇文章讲解注册的时候只是说了注册到容器里,并没有说明具体是注册到了哪里,这里点明一下,所谓讲BeanDefinition注册到容器里,就是将BeanDefinition放入到容器的一个Map里,具体是注册到了DefaultListableBeanFactorybeanDefinitionMap属性里,beanName会保存到beanDefinitionNames属性里,这是个list集合,里面的beanName会保持注册时候的顺序。

实例化的开始就是从遍历所有的beanName开始,话不多说,开始分析吧。

源码分析 bean实例化入口

还记得实例化入口的方法名吗?回忆一下,算了,反正也不会有人记得。是beanFactory.preInstantiateSingletons(),具体实现是在DefaultListableBeanFactory类里。

Spring Ioc源码解析:Bean实例化流程详解是怎样的?

跟进代码查看,可以看到,这段代码分为两部分,第一个for循环用于先实例化对象,第二个for循环完成一些实例化之后的回调操作。我们先来看第一个for循环,首先是遍历所有的beanNames获取BeanDefinition,然后根据工厂bean非工厂bean进行相应处理,最后调用getBean(beanName)实例化对象。注意这里实例化的是非抽象的、单例的并且是非懒加载的bean,这个前提非常重要。

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. // 所有bd的名称 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 遍历所有bd,一个个进行创建 for (String beanName : beanNames) { // 获取到指定名称对应的bd RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 对不是延迟加载的单例的Bean进行创建 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 判断是否是一个FactoryBean if (isFactoryBean(beanName)) { // 如果是一个factoryBean的话,先创建这个factoryBean,创建factoryBean时,需要在beanName前面拼接一个&符号 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 { // 判断是否是一个SmartFactoryBean,并且不是懒加载的,就意味着,在创建了这个factoryBean之后要立马调用它的getObject方法创建另外一个Bean isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // 不是factoryBean的话,我们直接创建就行了 getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... // 在创建了所有的Bean之后,遍历为所有适用的 bean 触发初始化后回调,也就是这里会对延迟初始化的bean进行加载... for (String beanName : beanNames) { // 这一步其实是从缓存中获取对应的创建的Bean,这里获取到的必定是单例的 Object singletonInstance = getSingleton(beanName); // 判断是否是一个SmartInitializingSingleton, // 最典型的就是我们之前分析过的EventListenerMethodProcessor, // 在这一步完成了对已经创建好的Bean的解析,会判断其方法上是否有 @EventListener注解, // 会将这个注解标注的方法通过EventListenerFactory转换成一个事件监听器并添加到监听器的集合中 if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } } 获取BeanDefinition

首先跟进getMergedLocalBeanDefinition(beanName)方法,这里首先会尝试从mergedBeanDefinitions里去获取,这个mergedBeanDefinitions存放着已经合并过的BeanDefinition,获取不到再真正调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))去获取。

/** * Return a merged RootBeanDefinition, traversing the parent bean definition * if the specified bean corresponds to a child bean definition. * * 返回一个合并的 RootBeanDefinition,如果指定的 bean 对应于子 bean 定义,则遍历父 bean 定义。 * * @param beanName the name of the bean to retrieve the merged definition for * @return a (potentially merged) RootBeanDefinition for the given bean * @throws NoSuchBeanDefinitionException if there is no bean with the given name * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. // 首先检查 mergedBeanDefinitions ,最小程度影响并发性能 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null && !mbd.stale) { return mbd; } return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); }

先看getBeanDefinition(beanName),这个方法就是简单的去beanDefinitionMap里获取BeanDefinition,如果获取不到,就抛出异常。beanDefinitionMap就是上面说到的BeanDefinition存放的地方。

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { if (logger.isTraceEnabled()) { logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } return bd; }

接下来就进入到getMergedBeanDefinition()方法获取BeanDefinition,为啥要从beanDefinitionMap获取了还进行一个merged获取呢?这是因为Bean有层次关系,子类需要合并父类的属性方法等,所以要进行一次合并,合并完成后会放入到mergedBeanDefinitions里,功能和属性名区分度还是十分贴切的

本文共计1584个文字,预计阅读时间需要7分钟。

Spring Ioc源码解析:Bean实例化流程详解是怎样的?

Spring Ioc 源码解析系列--Bean 实例化过程(一)前言+上一篇文章Spring Ioc 源码解析系列--IoC 容器注册BeanPostProcessor处理器以及事件消息处理器已完成,对IoC容器启动方法refresh()也进行了解析。

Spring Ioc源码分析系列--Bean实例化过程(一) 前言

上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对IoC容器启动方法也就是refresh()方法的简单分析。但是之前的分析在对容器实例化Bean的过程的略过了,留到了这后续的文章分析,所以这篇文章会对Bean的实例化过程做一个介绍。

首先来理一下本文的思路:关键词是实例化。由于Spring是利用反射实现的实例化,脑子里先简单想一下Java里利用发射实例化一个对象需要哪些步骤和操作。毫无疑问,我们首先要知道对象的class,接着需要确定使用什么构造函数以及确定构造函数的参数等。利用这些已经基本可以实现一个对象的实例化,当然实际上需要的东西可能更多更复杂,这里只是举个例子。那么需要的这些信息可以去哪里提取呢?对Spring有了解的可能都马上能想到BeanDefinition,这是一份原料表,里面有我们构造一个实例化对象所需的所有参数。如果不太理解这个定义,可以参考一下上篇文章的例子。

如果不清楚BeanDefinition是从哪里来的以及不清楚如何定义的,可以参考之前的文章Spring Ioc源码分析系列--Ioc源码入口分析的关键实现系列方法 loadBeanDefinitions ()。这篇文章讲解注册的时候只是说了注册到容器里,并没有说明具体是注册到了哪里,这里点明一下,所谓讲BeanDefinition注册到容器里,就是将BeanDefinition放入到容器的一个Map里,具体是注册到了DefaultListableBeanFactorybeanDefinitionMap属性里,beanName会保存到beanDefinitionNames属性里,这是个list集合,里面的beanName会保持注册时候的顺序。

实例化的开始就是从遍历所有的beanName开始,话不多说,开始分析吧。

源码分析 bean实例化入口

还记得实例化入口的方法名吗?回忆一下,算了,反正也不会有人记得。是beanFactory.preInstantiateSingletons(),具体实现是在DefaultListableBeanFactory类里。

Spring Ioc源码解析:Bean实例化流程详解是怎样的?

跟进代码查看,可以看到,这段代码分为两部分,第一个for循环用于先实例化对象,第二个for循环完成一些实例化之后的回调操作。我们先来看第一个for循环,首先是遍历所有的beanNames获取BeanDefinition,然后根据工厂bean非工厂bean进行相应处理,最后调用getBean(beanName)实例化对象。注意这里实例化的是非抽象的、单例的并且是非懒加载的bean,这个前提非常重要。

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. // 所有bd的名称 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 遍历所有bd,一个个进行创建 for (String beanName : beanNames) { // 获取到指定名称对应的bd RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 对不是延迟加载的单例的Bean进行创建 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 判断是否是一个FactoryBean if (isFactoryBean(beanName)) { // 如果是一个factoryBean的话,先创建这个factoryBean,创建factoryBean时,需要在beanName前面拼接一个&符号 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 { // 判断是否是一个SmartFactoryBean,并且不是懒加载的,就意味着,在创建了这个factoryBean之后要立马调用它的getObject方法创建另外一个Bean isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // 不是factoryBean的话,我们直接创建就行了 getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... // 在创建了所有的Bean之后,遍历为所有适用的 bean 触发初始化后回调,也就是这里会对延迟初始化的bean进行加载... for (String beanName : beanNames) { // 这一步其实是从缓存中获取对应的创建的Bean,这里获取到的必定是单例的 Object singletonInstance = getSingleton(beanName); // 判断是否是一个SmartInitializingSingleton, // 最典型的就是我们之前分析过的EventListenerMethodProcessor, // 在这一步完成了对已经创建好的Bean的解析,会判断其方法上是否有 @EventListener注解, // 会将这个注解标注的方法通过EventListenerFactory转换成一个事件监听器并添加到监听器的集合中 if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } } 获取BeanDefinition

首先跟进getMergedLocalBeanDefinition(beanName)方法,这里首先会尝试从mergedBeanDefinitions里去获取,这个mergedBeanDefinitions存放着已经合并过的BeanDefinition,获取不到再真正调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))去获取。

/** * Return a merged RootBeanDefinition, traversing the parent bean definition * if the specified bean corresponds to a child bean definition. * * 返回一个合并的 RootBeanDefinition,如果指定的 bean 对应于子 bean 定义,则遍历父 bean 定义。 * * @param beanName the name of the bean to retrieve the merged definition for * @return a (potentially merged) RootBeanDefinition for the given bean * @throws NoSuchBeanDefinitionException if there is no bean with the given name * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. // 首先检查 mergedBeanDefinitions ,最小程度影响并发性能 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null && !mbd.stale) { return mbd; } return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); }

先看getBeanDefinition(beanName),这个方法就是简单的去beanDefinitionMap里获取BeanDefinition,如果获取不到,就抛出异常。beanDefinitionMap就是上面说到的BeanDefinition存放的地方。

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { if (logger.isTraceEnabled()) { logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } return bd; }

接下来就进入到getMergedBeanDefinition()方法获取BeanDefinition,为啥要从beanDefinitionMap获取了还进行一个merged获取呢?这是因为Bean有层次关系,子类需要合并父类的属性方法等,所以要进行一次合并,合并完成后会放入到mergedBeanDefinitions里,功能和属性名区分度还是十分贴切的