• 理解 Spring IoC 容器


    控制反转与大家熟知的依赖注入同理, 这是通过依赖注入对象的过程. 创建 Bean 后, 依赖的对象由控制反转容器通过构造参数 工厂方法参数或者属性注入. 创建过程相对于普通创建对象的过程是反向, 称之为控制反转 (IoC).

    Tomcat 也是 IoC 的一个 Bean

    ApplicationContext

    ApplicationContext 是 Spring IoC 容器实现的代表, 它负责实例化, 配置和组装 Bean.

    IoC 使用元数据配置这种形式, 这个配置元数据表示了应用开发人员告诉 Spring 容器以何种方式实例化 配置和组装应用程序中的对象.

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. https://www.springframework.org/schema/beans/spring-beans.xsd">
    6. <bean id="..." class="..."> (1) (2)
    7. bean>
    8. <bean id="..." class="...">
    9. bean>
    10. beans>

    除了 id 和 class 外,  标签支持指定 factory-bean factory-method 标识容器以何种方式实例化对象.

    元数据

    元数据 (BeanDefinition), 一种类似于 java.lang.Class 的定义格式.

    1. SpringApplication.run
    2. AbstractApplicationContext.refresh
    3. AbstractRefreshableApplicationContext.refreshBeanFactory
    4. BeanDefinitionRegistry.registerBeanDefinition (多为 ConcurrentHashMap)

    容器对通过 xml 或是其他方式定义的解析成 BeanDefinition 对象, 并保存在 BeanDefinitionRegistry.beanDefinitionMap(ConcurrentHashMap) 中.

    BeanDefinition 包括 factory-bean 和 factory-method 以备创建实例.

    注意:如果没有指定构造器这种方式, 会选择无参构造器去创建. 事实上, 大部分构造方式都是无参构造创建, 再由DI setter 注入. 如: Controller Service 等

    Bean 和 getBean

    容器没有直接提供一个方法去 set 对象到容器里, 对外只暴漏了 getBean 这个方法. 容器中如果没有 Bean 实例, 这时才会去创建实例.

    为了便于理解, 我会分开说.

    • getBean 获取
    1. AbstractBeanFactory.getBean
    2. AbstractBeanFactory.doGetBean
    3. SingletonBeanRegistry.getSingleton (多为 ConcurrentHashMap)
    • createBean 创建
    1. AbstractBeanFactory.getBean
    2. AutowireCapableBeanFactory.createBean
    3. AutowireCapableBeanFactory.doCreateBean
    4. BeanDefinitionRegistry.getBeanDefinition (多为 ConcurrentHashMap)
    5. instantiate (getDeclaredConstructor)
    6. SingletonBeanRegistry.addSingleton (多为 ConcurrentHashMap)

    容器将创建好的 Bean addSingleton 到 SingletonBeanRegistry.singletonObjects(ConcurrentHashMap) 中. 需要时, getSingleton 可以直接获取.

    Bean 整体加载过程如上, 可以看出在 loadClass 没有被重载的情况下, 走的还是 JVM 的双亲委派.

    扫描与注解

    之前提到过除了 xml 还可以使用其他方式, 比较常见的就是注解的方式, 这种方式一般搭配扫描注解一起使用. 其实本质上还是找到类的 Class 并且 loadBeanDefinitions 供 instantiate 方法来使用.

  • 相关阅读:
    2.15 OrCAD中怎么创建带图片的Title Block?【OrCAD原理图封装库50问解析】
    JavaScript正则表达式
    小程序开发---02认识宿主环境
    链接装载与库:第八章——Linux共享库组织
    狂神说笔记 快速入门Nginx
    无需搭建环境,零门槛带你体验Open-Sora文生视频应用
    九小场所安全隐患排查—线上隐患上报、整改
    自媒体赚钱方式有哪些?如何高效运营自媒体
    【Linux操作系统实战】Linux基础命令面试必备(二)
    基于大数据的学习资源推送系统
  • 原文地址:https://blog.csdn.net/xiaohao718/article/details/126761048