7

理解 Spring IoC 容器 - mossxzzom

 1 year ago
source link: https://www.cnblogs.com/mossxzzom/p/16666395.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

Tomcat 也是 IoC 的一个 Bean

ApplicationContext

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

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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="..."> (1) (2)
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

除了 id 和 class 外, <bean></bean> 标签支持指定 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 方法来使用.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK