首页 > 编程语言 >Spring Bean实例化:从源码窥探生命之源

Spring Bean实例化:从源码窥探生命之源

时间:2024-05-30 14:33:59浏览次数:23  
标签:... 实例 mbd Spring beanName Bean 源码

1. 引言

在Spring框架中,Bean的生命周期是一个至关重要的概念,它涉及了Bean的创建、初始化、使用以及销毁等多个阶段。其中,Bean的实例化作为生命周期的起点,具有举足轻重的地位。以下将对Spring中Bean的实例化过程进行深度解析,结合源码分析,提供更深入的理解。


2. Bean实例化的背景与意义

在Spring的IOC(Inversion of Control,控制反转)容器中,Bean的实例化是容器管理Bean生命周期的第一步。通过实例化,Spring容器能够创建出开发者定义的Bean对象,为后续的依赖注入、初始化等操作奠定基础。因此,对Bean实例化过程的理解,是掌握Spring框架核心机制的关键。


3. Bean实例化的源码分析

  1. 扫描与解析
    • Spring启动时,会根据配置的包路径进行扫描,获取指定路径下的所有类文件。
    • 利用MetadataReaderFactory解析类文件,得到MetadataReader对象,该对象包含了类的元数据信息。
    • 通过excludeFiltersincludeFilters以及条件注解@Conditional的筛选,确定哪些类需要被Spring容器管理。
  2. BeanDefinition的创建
    • BeanDefinition是Spring框架中描述Bean的元数据信息的接口,具体实现类有RootBeanDefinition等。
    • Spring会读取配置文件或注解中的类名、作用域、属性等信息,并设置到BeanDefinition对象中。
  3. 实例化过程
    • Spring通过AbstractBeanFactorydoGetBean方法获取Bean实例。
    • 如果Bean是单例(isSingleton()true),则首先尝试从缓存中获取实例。
    • 如果缓存中没有,则调用getSingleton方法中的lambda表达式,通过createBean方法创建Bean实例。
      • createBean方法内部调用doCreateBean方法,该方法又调用instantiateBean方法实际创建Bean实例。
      • instantiateBean方法使用反射机制调用类的构造函数创建Bean实例。
    • 如果Bean是原型(prototype)或其他非单例类型,则每次调用getBean时都会重新创建实例。

以下是简化的源码片段:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {  
    // 实例化Bean之前的前置处理  
    // ...  
  
    // Instantiate the bean.  
    BeanWrapper instanceWrapper = null;  
    if (mbd.isSingleton()) {  
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
    }  
    if (instanceWrapper == null) {  
        // 使用指定的构造函数或默认构造函数实例化Bean  
        instanceWrapper = createBeanInstance(beanName, mbd, args);  
    }  
  
    // ... 依赖注入、初始化等后续步骤 ...  
  
    return instanceWrapper.getWrappedInstance();  
}  
  
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {  
    // ... 省略了部分逻辑 ...  
  
    // 确定实例化策略:通过构造函数、工厂方法等  
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
    if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {  
        return autowireConstructor(beanName, mbd, ctors, args);  
    }  
  
    // 默认使用无参构造函数实例化  
    return instantiateBean(beanName, mbd);  
}  
  
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {  
    try {  
        Object beanInstance;  
        final BeanFactory parent = this;  
        if (System.getSecurityManager() != null) {  
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->   
                getInstantiationStrategy().instantiate(mbd, beanName, parent),  
                getAccessControlContext());  
        } else {  
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
            // ... 省略了部分逻辑 ...  
        }  
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
        initBeanWrapper(bw);  
        return bw;  
    } catch (Throwable ex) {  
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
    }  
}
  1. 依赖注入
    • 在Bean实例创建后,Spring会根据BeanDefinition中配置的依赖关系,通过populateBean方法进行依赖注入。
    • 依赖注入可以通过属性注入、构造函数注入等方式实现。
  2. Bean后处理器
    • 如果存在Bean后处理器(BeanPostProcessor),则Spring会在Bean实例化之后、初始化之前调用Bean后处理器的postProcessBeforeInitialization方法。
    • 在Bean初始化之后,Spring还会调用Bean后处理器的postProcessAfterInitialization方法。

4. 总结

Spring中Bean的实例化过程涉及扫描、解析、创建BeanDefinition、实例化Bean、依赖注入以及Bean后处理器等多个步骤。这些步骤共同确保了Bean的正确创建和初始化,为Spring框架的IOC容器提供了坚实的基础。通过深入解析这些步骤的源码,能够更好地理解Spring框架的工作原理,从而在实际开发中更好地运用它。


标签:...,实例,mbd,Spring,beanName,Bean,源码
From: https://blog.csdn.net/m0_51176516/article/details/139260858

相关文章

  • 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
     SpringDataJPA系列1、SpringBoot集成JPA及基本使用2、SpringDataJPACriteria查询、部分字段查询3、SpringDataJPA数据批量插入、批量更新真的用对了吗4、SpringDataJPA的一对一、LazyInitializationException异常、一对多、多对多操作5、SpringDataJPA自定......
  • SpringBoot整合Mybatis实现增删改查功能
    目录1.添加依赖2.配置数据源和MyBatis3.创建实体类4.Mapper接口与映射文件5.编写服务层6.控制器SpringBoot整合MyBatis是一个相对直接的过程,主要涉及添加依赖、配置数据源、配置MyBatis、创建实体类、Mapper接口和映射文件、以及编写服务层来实现增删改......
  • Java Microservices 和 Spring Cloud:介绍微服务架构,并使用Spring Cloud来说明其在Java
    介绍微服务架构是一种软件开发技术,它将一个大型的单体应用系统拆分为多个小的、独立的服务,每个服务都可以独立部署和运行,各个小服务之间通过网络连接进行通信(通常是用HTTP/REST或消息队列)。每一个微服务都围绕着一个特定的业务功能进行构建,它们独立运行,在自己的进程内进行数......
  • (小白专用)SpringBoot快速搭建
    SpringBoot简介跟优点SpringBoot是一个基于Spring框架的开源项目,用于简化和加速Spring应用程序的开发和部署过程。它通过提供默认配置和约定来简化Spring应用程序的搭建,从而让开发者更专注于编写业务逻辑而不是配置和设置。SpringBoot的主要特点包括:自动配置:Spr......
  • springboot~jpa审计字段的自动填充
    在使用SpringDataJPA中的@CreatedDate注解时,如果希望自动填充创建时间字段,通常需要结合@EntityListeners(AuditingEntityListener.class)注解一起使用。这是因为@CreatedDate等审计注解通常与审计事件监听器(AuditingEntityListener)一起工作,用于处理实体的审计信息。审......
  • 校园台球厅人员与设备|基于SprinBoot+vue的校园台球厅人员与设备管理系统(源码+数据库
    校园台球厅人员与设备管理系统目录基于SprinBoot+vue的校园台球厅人员与设备管理系统一、前言二、系统设计三、系统功能设计 1系统功能模块2管理员功能模块3用户功能模块四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:......
  • 校友社交|基于SprinBoot+vue的校友社交系统(源码+数据库+文档)
    校友社交系统目录基于SprinBoot+vue的校友社交系统一、前言二、系统设计三、系统功能设计 1系统功能模块2后台功能模块5.2.1管理员功能模块5.2.2用户功能模块四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:博主介绍:✌️......
  • 大药房|基于SprinBoot+vue的大药房管理系统(源码+数据库+文档)
    大药房管理系统目录基于SprinBoot+vue的大药房管理系统一、前言二、系统设计三、系统功能设计 1系统功能模块2管理员功能模块四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:博主介绍:✌️大厂码农|毕设布道师,阿里云开发......
  • 网上书城|基于SprinBoot+vue的网上书城管理系统(源码+数据库+文档)
    网上书城管理系统目录基于SprinBoot+vue的网上书城管理系统一、前言二、系统设计三、系统功能设计 1系统功能模块2管理员功能模块3用户后台功能模块四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:博主介绍:✌️大厂码农|......
  • 基于springboot+vue的家乡特色推荐系统
    开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9系统展示系统首页用户注册文章分享界面个人中心管理员登录管理员功能用户管理文章分类管理文章分享......