会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 详解Spring 如何创建 Bean 对象?!

详解Spring 如何创建 Bean 对象?

时间:2025-11-05 15:56:04 来源:益强数据堂 作者:域名 阅读:721次

前情回顾前文「Spring 如何从 IoC 容器中获取对象?详解象」从整体上分析了如何从 Spring IoC 容器获取一个 bean 对象。该逻辑由 AbstractBeanFactory#doGetBean 方法实现,何创主要流程如下:

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

如何创建单例对象?详解象

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

值得注意是何创的:

只有对象是单例的场景,即 scope 为 singleton 时才会缓存对象。详解象 这里其实涉及到了所谓的何创「三级缓存」,为了更容易理解三级缓存,详解象本文先研究这个 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 虽然看起来有点像,但它俩不是一回事,前者是“实例化”,后者是“初始化”。

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

创建 bean 对象:createBeanInstance 方法 填充属性:populateBean 方法 初始化 bean:initializeBean 方法

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

就是这样。

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

小结

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

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

创建 bean 对象。 填充 bean 属性 初始化 bean 对象

至于这三个步骤具体又做了什么,香港云服务器且听下回分解。

(责任编辑:域名)

推荐内容
  • Kernel 4.2.3已经发布了,关于这个新版本有些什么新变化,这里不用说了,假如你是Ubuntu 用户,想升级到 Kernel 4.2.3 还是非常方便的,因为Ubuntu 提供了 DEB 安装包,减少了自行编译内核出现错误,当然也不是完全不会出错了,升级内核都有风险,所以谨慎操作。安装方法,直接命令行安装,打开终端。32位用户安装命令:下载安装包:安装内核:sudo dpkg -i linux-headers-4.2*.deb linux-image-4.2*.deb 假如觉得有问题或不好,卸载新版本内核命令:sudo apt-get remove linux-header-4.2* linux-image-4.2* 以上就是本文的全部内容,希望大家可以喜欢,可以帮助到大家。64位用户安装命令:下载安装包: 安装内核:sudo dpkg -i linux-headers-4.2*.deb linux-image-4.2*.deb 卸载内核:sudo apt-get remove linux-headers-4.2* linux-image-4.2
  • Django 开发人员的 7 个数据库优化最佳实践
  • 攻击者如何绕过常用的Web应用防火墙?
  • CACTI基本设置之设置Net-SNMP
  • 华硕TP550LJ笔记本电脑的性能和使用体验(华硕TP550LJ笔记本电脑的功能和性价比分析)
  • 在Ubuntu上安装和配置MySQL保姆级教程