SpringFramework — IOC总结&面试题整理

小龙 508 2022-06-01

SpringFramework 的基本知识

SpringFramework 概述

SpringFramework 是一个开源的、松耦合的、分层的、可配置的一站式企业级 Java 开发框架,它的核心是 IOC 和 AOP,使用它可以更容易的构建出企业级 Java 应用,并且它可以根据应用开发的组件需求,整合对于的技术。

为什么使用 SpringFramework

SpringFramework 支持 IOC、AOP、容器与事件、web、事务控制、测试、快捷的与其他技术整合
IOC:组件之间解耦(有强依赖降为若依赖)
AOP:切面编程可以将应用业务做统一或特定的功能增强,能够实现应用业务与增强逻辑的解耦
容器与事件:管理应用中使用的组件 Bean、托管 bean 的生命周期、事件与监听器的驱动机制

SpringFramework 的模块划分

  • beans、core、context、expression【核心包、容器】
  • aop【切面编程】
  • jdbc【整合jdbc】
  • orm【整合 ORM 框架】
  • tx【事务控制】
  • web【web层技术】
  • test{单元测试}

IOC 相关

如何理解 IOC

IOC 控制反转是一种思想它的核心是将控制权交出去,交由IOC管理的思想,可以实现组件之间的解耦。IOC 的实现方式通常有依赖注入和依赖查找

为什么使用 IOC

  • 解耦
  • 解决对象间的依赖关系
  • 托管对象的大部分生命周期过程,应用程序只需要关心使用过程、

IOC 的实现方式及对比

IOC 仅仅是一种思想,依赖查找DL和依赖注入DI才是 IOC 的落地实现。DL和DI的对比如下

  • 作用目标不同:
    • 依赖注入的作用目标通常是类成员(当然也可以是方法参数)
    • 依赖查找的作用目可以是方法体内,也可以是方法体外
  • 实现方式不同
    • 依赖注入通常借助一个上下文 被动 的接收(标注 @Autowired 注解/ <property>标签配置)
    • 依赖查找通常 主动 使用上下文搜索(拿到 BeanFactory / ApplicationContext 之后主动调用 getBean 方法)

IOC 在SpringFramework中的实现方式

依赖查找

  • getBean:根据 bean name 获取 / 根据 Class 获取指定的 bean
  • ofType:根据 Class 获取容器中所有指定类型的 bean
  • withAnnotation:获取标注了指定容器注解的 bean
  • getBeanDefinitionNames:获取容器中所有的 bean 的 name
  • getBeanProvider:延迟操作,先获取 ObjectProvider 后获取时机对象,如果不存在可以使缺省值代替

依赖注入

  • xml 配置文件驱动方式
    • 借助<property>标签给带有 setter 方法的属性赋值 / 注入依赖对象
    • 借助 <constructor-arg>标签使用 bean 的构造器注入依赖对象 / 属性赋值
  • 注解驱动方式
    • 使用 @Value 给普通属性赋值
    • 使用 @Autowired / @Resource / @Inject 注解给组件依赖注入
    • 借助 ObjectProvider 可以实现组件的延迟注入
  • 借助 Aware 系列接口实现回调注入

使用依赖注入的优点

  • 依赖注入作为 IOC 的实现方式之一,目的就是 解耦,我们不再需要去直接的 new 那些依赖对象(直接依赖会导致对象的创建机制、初始化过程难以统一控制);而且如果组件存在多级依赖。依赖注入可以简化这些依赖关系,开发者只需要定义好谁依赖谁即可。

  • 依赖注入还有另外一个特定就是依赖对象的 可配置:通过 xml 或注解声明,可以指定和调整组件注入的对象,借助 Java 的多态特性,可以不需要大批量的修改就可以完成依赖注入对象的替换(面向接口编程与依赖注入配合几乎完美)。

  • 依赖注入可以不需要依赖框架的API(仅仅依赖 JSR 规范也可以实现依赖注入),而依赖查找必须要拿到框架容器的 API,这一点也能看出依赖注入的一个优点:与框架 API 低耦合

依赖注入的方式对比

注入方式 被注入的成员是否可以变 是否依赖IOC框架的API 使用场景
构造器注入 不可变 否(xml。编程式注入不依赖) 不可变的固定场景
参数注入 不可变 否(高版本中注解配置类中的 @Bean 方法参数注入可不标注注解) 注解配置类中的 @Bean 方法注册 bean
属性注入 不可变 是(只能通过标注注解来侵入式注入) 通常用于不可变的固定注入
setter注入 可变 否(xml、编程时注入不依赖) 可选属性的注入

自动注入注解的对比

注解 注入方式 支持 @Primary 来源 Bean 不存在时的处理
@Autowired 根据类型注入 支持 SpringFramework的原生注解 可指定 required=fasle 来避免依赖不存在时抛出异常
@Resource 根据名称注入 支持 JSP 250规范 容器中不存在指定 Bean 时会抛出异常
@Inject 根据类型注入 支持 JSR 330规范(需要导入jar包) 容器中不存在指定 Bean 时会抛出异常

@Qualifer:如果被标注的成员 / 方法在根据类型注入时发现多个类型相同的 bean 时,则会根据该注解声明的 bean name 来寻找对应的 bean

@Primary:如果有多个相同类型的 bean 同时注册到 IOC 容器中,使用“根据类型注入”的注解时会直接注入 @Primary 标注的 bean

使用 setter 注入还是构造器注入

  • SpringFramework 4.0.2 及以前推荐使用 setter 注入,理由是:一个 Bean 有多个依赖时,构造器的参数列表会很长 ;而且如果 Bean 中依赖的属性不都是必须的话,注入会变得更麻烦

  • 4.0.3 开始以后官方推荐构造器注入,理由是:构造器注入的依赖是不可变的、完全初始化好的,并且可以保证不为null

  • 当然官方文档也说了,如果 真的出现了构造器参数列表过长的情况,可能是这个 Bean 承担的职责太多,应该考虑组件的责任拆解

SpringFramework 中的自动注入模式

  • byType:根据类型注入
  • byName:根据名称注入
  • byConstructor:根据构造器注入
  • autodetect:通过类的内省机制决定使用哪种方式注入
    • 顺序:byConstructor -> byType
  • no:不自动注入(默认)

IOC 容器相关

BeanFactory 和 ApplicationContext 的区别

BeanFactory 是实现 IOC 的顶层接口,它提供了一个抽象的配置和对象管理机制,ApplicationContext 是 BeanFactory 的子接口,它简化了和 AOP 的整合、消息机制、事件机制,以及对 Web 环境的扩展(WebApplicationContext 等)。ApplicationContext 是基于 BeanFactory 的扩展而不是继承 !

  • AOP 支持(AnnotationAwareAspectJAutoProxyCreator 作用于 bean 的初始化之后)
  • 配置元信息(BeanDefinition、Environment、注解等)
  • 资源管理(Resource抽象)
  • 事件驱动机制(ApplicationEvent、ApplicationListener)
  • 消息与国际化(LocaleResolver)
  • Environment 抽象
feature BeanFactory ApplicationContext
Bean Instantion/wiring —— Bean 的实例化和属性注入 Yes Yes
Integrated lifecycle management —— 生命周期管理 No Yes
Automatic BeanPostProcess registration —— Bean 后置处理器的支持 No Yes
Automatic BeanFactoryPostProcessor registration —— BeanFactory 的后置处理器支持 No Yes
Convenient MessageSource access(for internalization)—— 消息转换服务(国际化) No Yes
Built-in ApplicationEvent publication mechanism —— 时间发布机制(事件驱动) No Yes

除此之外,可以适当的引用官方文档的内容(可参照第 6 章 2.1 节)加以阐述,增加论述的可靠性。

ApplicationContext 的类型

从支持的配置源的角度来看,ApplicationContext 分为两种:基于 xml 配置文件的 ApplicationContext,和基于注解驱动配置类的 ApplicationContext。其中基于 xml 配置文件的 ApplicationContext 又有 ClassPathXMLApplicationContextFileSystemXMLApplicationContext 两种,它们的区别是在加载 xml 配置文件的基础路径不同;基于注解的 ApplicationContext 只有 AnnotationConfigApplicationContext,它可以基于配置类驱动,也可以基于包扫描路径驱动

可以参照第 15 章 ApplicationContext 全解析的内容辅以理解。

BeanFactory 和 FactoryBean 区别

BeanFactory:是 SpringFramework 中实现 IOC 的最底层容器;从类的继承结构上看,它是最顶级的接口,也是最顶层的容器实现;从类的组合结构上看,它是最深层次的容器,ApplicationContext 在最底层组合了 BeanFactory

FactoryBean:创建对象的工厂 Bean ,可以使用它来直接创建一些初始化流程比较复杂的对象。

BeanFactory 的设计

从接口设计角度来看:BeanFactory 是 IOC 的基础实现,最基础的 BeanFactory 只具备 依赖查找 的能力,它的直接子接口分别增加了 BeanFactory 的 层次性可列举性可配置 的特性

从实现的设计交底:BeanFactory 的实现类中,大多采用 父类控制流程 + 子类实现细节 的方式完成底层的功能逻辑,在父类中使用大量模板方法来控制整体的逻辑流程,由子类实现这些模板方法,完成功能的真正实现。

BeanFactory 本身具有以下一些特性:

  • 基础的容器(DL、DI)
  • 定义了作用域的概念(scope)
  • 集成环境配置(Environment)
  • 支持多种类型的配置源(Resource、PropertySource)
  • 层次性的设计(Hierarchical)
  • 完整的生命周期控制(createBean 定义在 BeanFactory 中,而不是 ApplicationContext 中)

在理解 BeanFactory 的时候,一定要从多方位的角度出发理解,结合第 14 章的内容理清 BeanFactory 中实现的功能、特性,以及在应用中发挥的作用。

ApplicationContext 的设计

从接口设计角度:ApplicationContext 继承了 BeanFactory 接口,它具备 BeanFactory 本身的特性;除此之外,ApplicationContext 还继承了多个接口,扩展了资源加载解析消息国际化事件发布等特性

从实现设计角度:ApplicationContext 分为 xml 配置文件注解驱动两种不同的驱动实现,它们的实现方法与 BeanFactory 相似,也是采用 父类控制流程 + 子类实现细节 的方式设计。

扩展特性:

  • 用于访问应用程序组件的 Bean 工厂方法,继承自 ListableBeanFactory
  • 以通用方法加载文件资源的能力,它继承自 ResourceLoader
  • 能够将事件发布给注册的监听器,它继承自 ApplicationEventPublisher
  • 解析消息的能力,支持国际化,它继承自 MessageSource
  • 从父上下文继承,在子容器中的定义将始终优先。(ApplicationContext 也具有层次性)

在理解 ApplicationContext 的时候不要一味地想着 ApplicationContext 是 BeanFactory 的子类扩展,它与 BeanFactory 的关系是组合关系,包括继承了其他接口后底层也都是组合这些接口对应功能的核心API。

Environment 的设计

Environment 是 SpringFramework 3.1 引入的抽象的概念,它包含了 profilesproperties 的信息,可以实现统一的配置存储和注入、配置属性的解析等。其中 profiles 实现了一种基于模式的环境配置,properties 则应用于外部化配置

如何理解 BeanDefinitionRegistry

BeanDefinitionRegistry 是维护 BeanDefinition 的注册中心,它内部存放了 IOC 容器总 bean 的定义信息,同时 BeanDefinitionRegistry 也是支撑其它组件和动态注册 Bean 的重要组件。在 SpringFramework 中,BeanDefinitionRegistry 的实现的 DefaultListableBeanFactory

BeanDefinitionRegistry 针对的目标是 BeanDefinition 而不是 bean 对象

对比 BeanFactory 与 BeanDefinitionRegistry

BeanFactory:SpringFramework 中实现 IOC 的最底层容器,内部存放了应用中注册的 Bean 实例

BeanDefinitionRegistry:BeanDefinition 的注册表,它维护的对象是 BeanDefinition 而不是 bean 实例

BeanFactoryPostProcessor

BeanFactoryPostProcessor 的设计

BeanFactoryPostProcessor 是容器的扩展点,它用于 IOC 容器生命周期中,所有 BeanDefinition 都注册到 BeanFactory 后回调触发,用于访问 / 修改已经存在的 BeanDefinition。与 BeanPostProcess 相同,它们都是容器隔离的,不同容器中的 BeanFactoryPostProcessor 不会相互起作用

后置处理器对比

BeanPostProcessor BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor
处理目标 bean BeanDefinition BeanDefinition、.class 文件等
执行时机 bean 的初始化阶段前后(已经创建出 bean 对象) BeanDefinition 解析完毕,注册进 BeanDefinition 之后(此时Bean 还未实例) 配置文件、配置类已经解析完毕并注册进BeanFactory。但还没有被 BeanFactoryPostProcessor 处理
可操作空间 给 bean 的属性赋值、创建代理对象等 给BeanDefinition中增删属性、移除 BeanDefinition 等 向 BeanFactory 中注册新的 BeanDefinition

Bean相关

Bean 的类型有哪些

SpringFramework 中的 bean 只有两种类型:普通 bean 和工厂 baen(FactoryBean 创建的对象)
普通 bean:就是最最普通的 bean 对象,SpringFramework 中绝大部分创建的 bean 都是普通 bean
工厂 bean:由 FactoryBean 创建的 bean 就是 工厂 bean,工厂 bean 不会在实际的业务逻辑中起作用,而是由创建的对象来起作用。FactoryBean 本身只是一个接口,它只是创建真正 bean 对象的工厂。

Bean 的作用域有哪些

在SpringFramework 5.x 版本中内置了 6 中作用域

作用域类型 概述
Singleton 一个 IOC 容器中只有一个相同类型的 bean(默认)
prototype 每次获取创建一个新的
request 一次请求创建一个新的(仅web环境可用)
session 一个会话创建一个新的
application 一个web应用创建一个
websocket 一个websocket会话创建一个

Bean 的实例化方式

SpringFramework 中实例化 bean 的方式,分为 4 种普通方式 + 1 种特殊方式

  • 直接通过 <bean> / @Bean /@Component 的方式注册 Bean 后实例化
  • 借助 FactoryBean 实例化 bean
  • 使用静态工厂方法(factory-method)实例化 bean
  • 使用实例工厂方法(factory-bean + factory-method)实例化 bean
  • 借助 InstantiationAwareBeanPostProcessor 实例化 bean(该方法比较特殊,实际上就是拦截原有 bean 的创建流程而是)

Bean 初始化 / 销毁的三种生命周期控制方法对比

init-method & destroy-method @PostConstruct & @PreDestroy InitlizingBean & DisposableBean
执行顺序 最后 最先 中间
组件耦合 无侵入(自在<bean> 和 @Bean 中使用) 与 JSR 规范耦合 与 SpringFramework 耦合
容器支持 xml、注解原生支持 注解原生支持,xml 需要开启注解驱动 xml、注解原生支持
单实例 Bean
原型 Bean 只支持 init-method

如何理解 BeanDefinition

BeanDefinition 描述了 SpringFramework 中 Bean 的元信息,它包含 Bean 的类信息、属性、行为、依赖关系、配置信息等。BeanDefinition 具有层次性,并且可以在 IOC 容器初始化阶段被 BeanDefinitionRegistryPostProcessor 构造和注册,被 BeanFactoryPostProcessor 拦截修改等

设计 BeanDefinition 的意义

SpringFramework 面对一个应用程序,它需要对其中的 Bean 进行定义抽取,只有抽取成可以统一类型 / 格式的模型,才能在后续的 Bean 对象管理时,进行统一管理,或者对特定的 Bean 进行特殊化的处理。而这一切的一切最终落地到统一类型上,就是 BeanDefinition 这个抽象化的模型。先有定义,后有实例,这样更容易实现全流程的控制和扩展的切入

BeanPostProcess

BeanPostProcess 的设计

BeanPostProcess 是一个容器的扩展点,它针对的是 Bean 对象,可以在 Bean 的生命周期过程中,初始化阶段前后添加自定义的处理逻辑,并且不同的 IOC 容器的 BeanPostProcess 不会互相干预。

BeanPostProcess 的扩展

在 SpringFramework 内部,BeanPostProcess 的扩展有三种:

  • InstantiationAwareBeanPostProcessor:作用于 Bean 对象的实例化前后,以及属性赋值阶段
  • MergedBeanDefinitionPostProcessor:作用于 BeanDefinition 的合并阶段,借助它可以完成层级 Bean 的定义信息汇总
    • 如 AutowiredAnnotationBeanPostProcessor 会收集 Bean 所设计类及 bean 所属类的父类中自动注入信息
  • DestructionAwareBeanPostProcessor:作用于 Bean 对象的销毁动作之前

单实例 Bean 的线程安全问题

SpringFramework 中的 Bean 默认单实例的,是线程不安全的,如果 Bean 存在多种状态,则需要考虑换位 prototype(原型)作用域类型的 Bean

通常情况下,Singleton 用于无状态 Bean,Prototype 用于有状态的 Bean

Bean 的生命周期

Bean 的生命周期分为 BeanDefinition 阶段和 Bean 实例阶段

  • BeanDefinition:该阶段分为加载 xml 配置文件解析注解配置类编程式构造 BeanDefinitionBeanDefinition 的后置处理,一共四个部分

  • Bean 实例化阶段,该阶段的生命周期包含四大步:

    • bean 的实例化
    • 属性注入 + 依赖注入
    • bean 的初始化生命周期回调
    • bean 实例的销毁

BeanDefinition 阶段生命周期

  • 加载 xml 配置文件:发生在基于 xml 配置文件的 ApplicationContextrefresh() 方法的 BeanFactory 初始化阶段,此时 BeanFactory 刚刚构建完成,它会借助 XmlBeanDefinitionReader 来加载 xml 配置文件,并使用 DefaultBeanDefinitionDocumentReader 解析 xml 配置文件,封装声明的 <bean> 标签内容并转换为 BeanDefinition

  • 解析注解配置类:发生在 ApplicationContextrefresh() 方法的 BeanDefinitionRegistryPostProcessor 阶段,该阶段首先会执行 ConfigurationClassPostProcessorpostProcessorBeanDefinitionRegistry 方法。ConfigurationClassPostprocessor 中会找出所有的配置类,排序后依次解析,并借助 ClassPathBeanDefinitionScanner 实现包扫描的 BeanDefinition 封装,借助 ConfigurationClassBeanDefinitionReader 实现 @Bean 注解方法的 BeanDefinition 解析和封装。

  • 编程式构造BeanDefinition 也是发生在 ApplicationContextrefresh() 方法的 BeanDefinitionRegistryPostProcessor 执行阶段,由于 BeanDefinitionRegistryPostProcessor 中包含 ConfigurationClassPostProcessor,而 ConfigurationClassPostProcessor 会执行 ImportBeanDefinitionRegistry 的逻辑,从而达到编程式构造 BeanDefinition 并注入到 BeanDefinitionRegistry 的目的;另外,实现了 BeanDefinitionRegistryPostProcessor 的类也可以编程式构造 BeanDefinition 注入到 BeanDefinitionRegistry

bean 实例化阶段的生命周期

在所有非延迟加载的单实例 bean 初始化之前,会先初始化所有的 BeanPostProcessor

ApplicationContextrefresh() 方法中,finishBeanFactoryInitialization 步骤会初始化所有的非延迟加载的单实例 bean。实例化 bean 的入口是 getBean() -> doGetBean(),该阶段会合并 BeanDefinition,并根据 beanscope 选择实例化 bean 的策略。

创建 bean 的逻辑会走 createBean() 方法,该方法中会先执行所有 InstantiationAwareBeanPostProcessorpostProcessorBeforeInstantiation() 方法尝试创建 bean 实例,如果成功创建,则会直接调用 PostProcessorAfterInstantiation() 方法初始化 bean 后返回,如果 InstantiationAwareBeanPostProcessor 没有创建 bean 实例,则会调用 doCreateBean() 方法创建 bean 实例。在 doCreateBean() 方法中,会先根据 bean 的 Class 中的构造器定义,决定如何实例化 bean,如果没有定义构造器,则会使用无参构造器,反射创建 bean 对象。

Bean 初始化阶段的生命周期

bean 对象创建完成后,会进行属性赋值依赖注入,以及初始化阶段的方法回调。在 populateBean 属性赋值阶段,会事先收集好 bean 中标注了依赖注入的注解(@Autowired@Value@Resource@Inject),之后会借助后置处理器,回调 PostProcessorProperties 方法实现依赖注入。

属性赋值和依赖注入之后,会调用执行 bean 的初始化方法,以及后置处理器的逻辑:首先会执行 Aware 相关的回调注入,之后执行后置处理器的前置回调,在后置处理器的前置方法中,会回调 bean 中标注了 @PostConstruct 注解的方法,所有的后置处理器前置回调后,会执行 InitializingBean 的 afterPropertiesSet 方法,随后是 init-method 指定的方法,等这些 bean 的初始化方法都回调完毕后,最后执行后置处理器的后置回调

全部的 bean 初始化结束后,ApplicationContext 的 start 方法触发时,会触发实现了 Lifecycle 接口的 bean 的 start 方法

Bean 销毁阶段的生命周期

bean 对象在销毁时,由 ApplicationContext 发起关闭动作。销毁 bean 的阶段,由 BeanFactory 取出所有单实例 bean ,并逐个销毁

销毁动作会将当前 bean 依赖的所有 bean 都销毁,随后回调那些自定义的 bean 的销毁方法,之后如果 bean 中有定义内部 bean 则会一并销毁,最后销毁那些依赖了当前 bean 的 bean 也一起销毁

Bean 装配相关

模块装配与条件装配

  • 模块装配:指用最少的代码,把一个模块需要的核心功能组件都装配好(通常使用自定义 @EnableXxxx 注解 + @Import 注解完成)。

    • @Import 支持装配的组件:普通类、注解配置类、ImportSelector、ImportBeanDefinitionRegistry
  • 条件装配:可以设定装配 bean 或配置类在特定条件下才生效,分为 profile 和 conditional 两种实现方式。

    • profile 基于 Environment 层,一般用于多环境配置
    • conditional 基于 bean 层,且 conditional 的判断方式更加灵活

组件扫描

利用组件扫描,可以扫描指定路径下的所有标注了模式注解的类,并封装生成 bean 对象。可以通过声明 @ComponentScan 注解中的 includeFilters 和 excludeFilters 属性来指定扫描的匹配规则。

SPI

SPI 是通过一种“服务寻找”的机制,动态的加载接口 / 抽象类对应的具体实现类,它把接口具体实现类的定义和声明权交给了外部化的配置文件中。

jdk 的 SPI 是需要遵循规范的:所有定义的 SPI 文件都必须放在工程的 META-INF/services 目录下,且文件名必须命名为接口 / 抽象类的全限定名,文件内容为接口 / 抽象类的具体实现类的全限定名,如果出现多个具体实现类,则每行声明一个类的全限定名,没有分隔符。

SpringFramework 中的 SPI 在要求上比较宽松,它不止可以基于接口 / 抽象类,还可以是任何一个类、接口、注解,并且这种机制被大量用于 SpringBoot 的自动装配中。

功能特性相关

事件与监听器

如何理解观察者模式

观察者模式,也被称为发布订阅模式、监听器模式,它是 GoF23 设计模式中行为型模式的其中之一。观察者模式关注的点是某一个对象被修改 / 做出某些反应 / 发布一个信息等,会自动通知依赖它的对象(订阅者)。观察者模式的三大核心是:观察者、被观察主题、订阅者。观察者( Observer )需要绑定要通知的订阅者( Subscriber ),并且要观察指定的主题( Subject )。

Spring中的观察者模式是如何体现的

SpringFramework 中,体现观察者模式的特性就是事件驱动和监听器。监听器充当订阅者,监听特定的事件;事件源充当被观察的主题,用来发布事件;IOC 容器本身也是事件广播器,可以理解成观察者。

SpringFramework 的事件驱动核心概念可以划分为 4 个:事件源事件广播器监听器

  • 事件源:发布事件的对象
  • 事件:事件源发布的信息 / 作出的动作
  • 广播器:事件真正广播给监听器的对象【即 ApplicationContext 】
    • ApplicationContext 接口有实现 ApplicationEventPublisher 接口,具备事件广播器的发布事件的能力
    • ApplicationEventMulticaster 组合了所有的监听器,具备事件广播器的广播事件的能力
  • 监听器:监听事件的对象

监听器的实现方式

  • 实现 ApplicationListener ,并指定要监听的事件类型
  • 普通 bean 的方法上标注 @EventListener 注解,同样可以生成一个监听器

Spring中内置的事件

  • ContextRefreshedEvent :IOC 容器刷新完毕但尚未启动,广播该事件
  • ContextClosedEvent :IOC 容器已经关闭但尚未销毁所有 Bean ,广播该事件
  • ContextStartedEvent :ApplicationContext 的 start 方法被触发,广播该事件
  • ContextStoppedEvent :ApplicationContext 的 stop 方法被触发,广播该事件

资源管理

SpringFramework 中的资源管理是内部封装的,它的核心资源模型接口 Resource 可以支持 ResourceLoader 从类路径等位置加载。根据资源的加载来源不同,Spring 划分了几种 Resource 的不同实现,并由 DefaultResourceLoader 委托 ProtocolResolver 来负责加载这些资源。

SpringFramework 可以支持 properties 、xml(yml)等类型的资源文件,这些资源会通过 PropertySourceFactory 加载进 Environment 中,成为应用内变量的一部分。

配置元信息

理解配置源

配置源,就是配置的来源。对于 IOC 容器而言,xml 配置文件或者注解配置类可以称之为配置源;对于 Environment 来讲,properties 资源文件也可以看作是配置源。SpringFramework 拿到配置源后会先加载,再解析,最后注册那些定义好的 bean 到 IOC 容器。

理解元信息

简单的理解,元信息,就是信息的信息定义的定义。举个例子,Class 这个类里面就包含一个类的所有定义(属性、方法、继承实现、注解等),所以我们可以说:Class 中包含类的元信息

Spring中的元信息

Spring 中的元信息可以简单的分为 Bean 的元信息、IOC 容器的元信息:

  • Bean 的元信息
    • 全限定名 className
      -作用域 scope
      -是否延迟加载 lazy
      -工厂 Bean 名称 factoryBean
      -构造方法参数列表 constructorArgumentValues
      -属性值 propertyValues
  • IOC 容器的元信息
    -beans ,包含 profile 、default-autowire 等配置
    -context ,包含 component-scan 、property-placeholder 、annotation-config 等配置

# 面试 # IOC