【从零构建Spring|第十四节】 自动扫描并注册Bean
【从零构建Spring|第十四节】 自动扫描并注册Bean
Shio【从零构建Spring|第十四节】 自动扫描并注册Bean
前言
在上一章节结束之后,我们其实已经完成了 IoC 和 AOP 的全部核心内容。但是现在还需要使用 Spring.xml 进行配置。思考思考我们平时最多是怎么用 Spring 完成信息配置的?一是注解,二是 property。
为了在核心逻辑上填充一些自动化的功能,所需要的知识有:
- 包的扫描注册
- 注解配置使用
- 占位符属性的填充
设计
为了可以简化 Bean 对象的配置,达到整个 Bean 对象的注册都是自动扫描的。最基本的元素包括:
- 扫描路径入口
- XML 解析扫描信息
- 给需要扫描的 Bean 对象做注解标记
- 扫描 Class 对象摘取 Bean 注册的基本信息
- 组装 Bean 注册信息
- 注册 Bean 对象
除此之外再顺带解决一个配置中占位符属性的知识点,比如可以通过 ${token}
给 Bean 对象注入进去属性信息,那么这个操作需要用到 BeanFactoryPostProcessor,因为它可以处理 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
结合 bean 的生命周期,包扫描只不过是扫描特定注解的类,提取类的相关信息组装成 BeanDefinition 注册到容器中。
在 XmlBeanDefinitionReader 中解析<context:component-scan />
标签,扫描类组装 BeanDefinition 然后注册到容器中的操作在 ClassPathBeanDefinitionScanner#doScan 中实现。
- 自动扫描注册主要是扫描添加了自定义注解的类,在 xml 加载过程中提取类的信息,组装 BeanDefinition 注册到 Spring 容器中。
- 所以我们会用到
<context:component-scan />
配置包路径并在 XmlBeanDefinitionReader 解析并做相应的处理。这里的处理会包括对类的扫描、获取注解信息等 - 最后还包括了一部分关于
BeanFactoryPostProcessor
的使用,因为我们需要完成对占位符配置信息的加载,所以需要使用到 BeanFactoryPostProcessor 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,修改 BeanDefinition 的属性信息。这一部分的实现也为后续处理关于占位符配置到注解上做准备
处理对象扫描装配
XML 解析类 XmlBeanDefinitionReader 对 ClassPathBeanDefinitionScanner#doScan 的使用
doScan 方法处理所有指定路径下添加注解的类,拆解出类的信息{ 名称 beanName,作用范围 scope }.在进行创建 BeanDefinition 用于 Bean 对象的注册操作。
详细代码:
- doScan 中,findCandidateComponents 负责将所有标注了 @Component 注解的类 通过 ClassUtil.scanPackageByAnnotation(basePackage, Component.class) 解析出来, Set<Class<?>> 维护 Class,Set 维护以及实例化好的 BeanDefinition(clazz)
- 对每个 BeanDefinition 而言,需要解析其 scope(可为 null)和 beanName。他们的解析都是通过获取注解内容的方式 getAnnotation(@interface.class)
PropertyPlaceholderConfigurer
目前看上去像一块单独的内容,后续会把这块的内容与自动加载 Bean 对象进行整合,也就是可以在注解上使用占位符配置一些在配置文件里的属性信息。
他所做的步骤如下:
- 读取属性文件资源,通过 load 方式将信息加载到 properties 类中
- 通过一些简单逻辑操作将占位符 “{@Value}” 替换成 “实际内容”
详细代码:
资源读取
迭代读取 XML 配置信息的代码,使用 dom4j 方式解析 xml,不仅提高代码简洁性,也提升易读性
<dependency> |