我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring 如何创建 Bean 对象

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring 如何创建 Bean 对象

这篇文章主要讲解了“Spring 如何创建 Bean 对象”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring 如何创建 Bean 对象”吧!

从整体上分析了如何从 Spring IoC 容器获取一个 bean 对象。该逻辑由  AbstractBeanFactory#doGetBean 方法实现,主要流程如下:

Spring 如何创建 Bean 对象

本文进一步深入细节,主要分析如何创建 singleton(单例)类型的对象。

如何创建单例对象?

从流程图可以看出,当获取一个 bean 对象时,Spring 会首先尝试从缓存中获取单例对象。

值得注意是的:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 只有对象是单例的场景,即 scope 为 singleton 时才会缓存对象。

  3. 这里其实涉及到了所谓的「三级缓存」,为了更容易理解三级缓存,本文先研究这个 bean 对象是什么时候放入缓存的,后面再研究三级缓存。

既然能取,必然有地方把 bean 对象存入了缓存,那缓存中的数据是从哪里来的呢?

下面主要分析单例对象是如何创建、并放入缓存中的。

该逻辑在 AbstractBeanFactory#doGetBean 方法中,主要代码如下(保留了创建单例 bean  对象的代码,其他部分暂时忽略):

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {     // ...      protected <T> T doGetBean(             String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)             throws BeansException {          String beanName = transformedBeanName(name);         Object bean;          // 从缓存中获取单例 bean 对象         Object sharedInstance = getSingleton(beanName);                  // 缓存中不存在 bean 对象         else {              // ...              try {                 // 获取 BeanDefinition                 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);                  // 获取依赖的 bean 对象                 // 若创建一个 bean 对象时依赖其他对象,则先创建被依赖对象                 // ...                  // 创建 scope 为 singleton(单例)的对象                 if (mbd.isSingleton()) {                     sharedInstance = getSingleton(beanName, () -> {                         try {                             return createBean(beanName, mbd, args);                         }                         catch (BeansException ex) {                             // ...                         }                     });                     // 处理 FactoryBean 的场景                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);                 }                  // 创建 scope 为 prototype 的对象                 else if (mbd.isPrototype()) {                     // ...                 }                  // 创建其他类型对象                 else {                     // ...                 }             }             catch (BeansException ex) {                 // ...             }         }          // 类型检查          return (T) bean;     } }

其实就是这个 DefaultSingletonBeanRegistry#getSingleton 方法,代码如下:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {     // 单例 bean 对象缓存(beanName, bean)     private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);      public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {         Assert.notNull(beanName, "Bean name must not be null");         synchronized (this.singletonObjects) {             // 先从缓存中获取 bean 对象             Object singletonObject = this.singletonObjects.get(beanName);             // 缓存中不存在时再去创建             if (singletonObject == null) {                 // ...                 // 创建单例对象前                 beforeSingletonCreation(beanName);                 boolean newSingleton = false;                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);                 if (recordSuppressedExceptions) {                     this.suppressedExceptions = new LinkedHashSet<>();                 }                 try {                     // 创建单例对象                     singletonObject = singletonFactory.getObject();                     newSingleton = true;                 }                 // catch ...                 finally {                     if (recordSuppressedExceptions) {                         this.suppressedExceptions = null;                     }                     // 创建单例对象后                     afterSingletonCreation(beanName);                 }                 if (newSingleton) {                     // 将对象添加到缓存                     addSingleton(beanName, singletonObject);                 }             }             // 缓存中有的话直接返回             return singletonObject;         }     }  }

getSingleton 方法会先从缓存 singletonObjects(其实就是一个 Map)中获取 bean  对象,如果缓存有就直接返回,否则再去创建。创建成功后,会把该对象存入缓存。

创建的逻辑在哪呢?

看代码是通过 ObjectFactory#getObject 方法来创建的,ObjectFactory 是一个函数式接口:

@FunctionalInterface public interface ObjectFactory<T> {     T getObject() throws BeansException; }

这个方法的实现是什么呢?退回上一层,即 getBean 方法,看这里:

sharedInstance = getSingleton(beanName, () -> {     try {         // 创建 bean 对象         return createBean(beanName, mbd, args);     }     catch (BeansException ex) {         // ...     } });

这里用到了 Lambda 表达式,将如下表达式作为参数:

() -> {     try {         // 创建 bean 对象         return createBean(beanName, mbd, args);     }     catch (BeansException ex) {         // ...     } }

创建 bean 对象的逻辑就在这个 createBean 方法中,它在 AbstractAutowireCapableBeanFactory  类中:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory         implements AutowireCapableBeanFactory {      @Override     protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)             throws BeanCreationException {          RootBeanDefinition mbdToUse = mbd;          Class<?> resolvedClass = resolveBeanClass(mbd, beanName);         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {             mbdToUse = new RootBeanDefinition(mbd);             mbdToUse.setBeanClass(resolvedClass);         }          // Prepare method overrides.         try {             mbdToUse.prepareMethodOverrides();         }         // catch ...          try {             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.             // 这里可能返回代理对象             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);             if (bean != null) {                 return bean;             }         }         // catch ...          try {             // 创建 bean 对象             Object beanInstance = doCreateBean(beanName, mbdToUse, args);             if (logger.isTraceEnabled()) {                 logger.trace("Finished creating instance of bean '" + beanName + "'");             }             return beanInstance;         }         // catch ...     } }
  • 值得注意的是,resolveBeforeInstantiation 方法其实是跟 AOP 实现相关的,可能在这里生成代理对象就返回了。由于现在主要分析  IoC 的流程,因此这里暂时略过,有兴趣的朋友们可以自行研究。

这里继续沿着主线逻辑走。

创建 bean 对象是在 doCreateBean 方法中实现的,如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory         implements AutowireCapableBeanFactory {      protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)             throws BeanCreationException {          // Instantiate the bean.         // 1. 实例化 bean         BeanWrapper instanceWrapper = null;         if (mbd.isSingleton()) {             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);         }         if (instanceWrapper == null) {             instanceWrapper = createBeanInstance(beanName, mbd, args);         }         Object bean = instanceWrapper.getWrappedInstance();         Class<?> beanType = instanceWrapper.getWrappedClass();         if (beanType != NullBean.class) {             mbd.resolvedTargetType = beanType;         }          // Allow post-processors to modify the merged bean definition.         synchronized (mbd.postProcessingLock) {             if (!mbd.postProcessed) {                 try {                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                 }                 // catch ...                 mbd.postProcessed = true;             }         }          boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                 isSingletonCurrentlyInCreation(beanName));         if (earlySingletonExposure) {             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));         }          // Initialize the bean instance.         Object exposedObject = bean;         try {             // 2. 填充属性             populateBean(beanName, mbd, instanceWrapper);             // 3. 初始化             exposedObject = initializeBean(beanName, exposedObject, mbd);         }         // catch ...          if (earlySingletonExposure) {             Object earlySingletonReference = getSingleton(beanName, false);             if (earlySingletonReference != null) {                 if (exposedObject == bean) {                     exposedObject = earlySingletonReference;                 }                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {                     String[] dependentBeans = getDependentBeans(beanName);                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);                     for (String dependentBean : dependentBeans) {                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {                             actualDependentBeans.add(dependentBean);                         }                     }                     // ...                 }             }         }          // Register bean as disposable.         try {             registerDisposableBeanIfNecessary(beanName, bean, mbd);         }         // catch ...          return exposedObject;     }  }
  • 注意:Instantiate 和 Initialize 虽然看起来有点像,但它俩不是一回事,前者是“实例化”,后者是“初始化”。

这个方法看起来有点长,但最主要的事情只有三件:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 创建 bean 对象:createBeanInstance 方法

  3. 填充属性:populateBean 方法

  4. 初始化 bean:initializeBean 方法

这几个方法内部其实都有一大堆堆堆堆堆&hellip;&hellip;的代码,再对照一下前面给出的整体流程图 :

Spring 如何创建 Bean 对象

就是这样。

本文在前文整体分析的基础上又进一步细化,先到这里吧,后面再继续分析~

小结

如何从 Spring IoC 容器中获取 bean 对象?前文对此进行了整体流程的分析。

本文在前文的基础上又进一步细化,主要从整体上探讨了 Spring 如何创建单例的 bean 对象,整体上分为三个步骤:

  1. 创建 bean 对象。

  2. 填充 bean 属性

  3. 初始化 bean 对象

感谢各位的阅读,以上就是“Spring 如何创建 Bean 对象”的内容了,经过本文的学习后,相信大家对Spring 如何创建 Bean 对象这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring 如何创建 Bean 对象

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

spring是如何注入对象的和bean创建过程分析

首先需要知道一个大致实现● 这个注入过程肯定是在 BeanPostProcessor 中实现的●spring 是在 beanFactory.getBean 进行 bean 实例化的,即懒加载● 根据第二条,也就是说在 getBean 的时候才会去调用所有 Be
spring是如何注入对象的和bean创建过程分析
2019-05-21

如何创建ADO.NET对象

这篇文章主要介绍“如何创建ADO.NET对象”,在日常操作中,相信很多人在如何创建ADO.NET对象问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何创建ADO.NET对象”的疑惑有所帮助!接下来,请跟着小编
2023-06-17

如何创建CLR对象

这篇文章主要介绍了如何创建CLR对象,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一 创建CLR对象1.在解决方案中添加新的C#SQL数据库项目,命名为“ServiceCli
2023-06-17

Spring复杂对象怎么创建

本文小编为大家详细介绍“Spring复杂对象怎么创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring复杂对象怎么创建”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。什么是复杂类型,比如连接数据库的Con
2023-06-26

Spring Boot如何动态创建Bean示例代码

前言本文主要给大家介绍了关于Spring Boot动态创建Bean的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。SpringBoot测试版本:1.3.4.RELEASE参考代码如下:package com.sp
2023-05-31

JavaScript中如何创建对象

今天就跟大家聊聊有关JavaScript中如何创建对象,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。JavaScript有什么特点1、js属于一种解释性脚本语言;2、在绝大多数浏览器
2023-06-14

java如何创建date对象

Java中可以使用以下几种方法来创建Date对象:1. 使用无参构造函数创建一个表示当前日期和时间的Date对象:```javaDate date = new Date();```2. 使用指定的毫秒数创建一个Date对象,该毫秒数表示从1
2023-09-13

unity如何创建空对象

在Unity中,创建空对象很简单。可以通过以下步骤创建空对象:1. 在Unity编辑器中,选择要在场景中创建空对象的位置。2. 右键点击场景窗口中的位置,然后选择“Create Empty”(创建空对象)。3. Unity将在选择的位置创建
2023-08-20

怎么在Spring IOC中创建对象

这篇文章将为大家详细讲解有关怎么在Spring IOC中创建对象,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、 使用无参构造创建对象(默认方式)创建实体类注意:属性必须要有set方法,来
2023-06-14

J2EE如何创建Enterprise Bean

这篇文章主要介绍“J2EE如何创建Enterprise Bean”,在日常操作中,相信很多人在J2EE如何创建Enterprise Bean问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”J2EE如何创建Ent
2023-06-03

spring Bean创建方法是什么

本篇内容主要讲解“spring Bean创建方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“spring Bean创建方法是什么”吧!bean创建的流程图写在前面:建议大家一定要自己用实
2023-06-26

编程热搜

目录