& 【04】 Spring中Xml属性配置的解析过程

Spring容器加载方式

  1. 类路径获取配置文件(ClassPathXmlApplicationContext)
  2. 文件系统路径获取配置文件绝对路径(FileSystemXmlApplicationContext)("绝对路径")
  3. 无配置文件加载容器(AnnotationConfigApplicationContext)
  4. SpringBoot加载容器(EmbeddWebApplicationContext)

Spring中Xml属性配置的解析过程

gitee

spring-framework:https://gitee.com/zb224989/spring-framework.git

refresh()方法中的obtainFreshBeanFactory()负责把解析出来的xml标签封装成BeanDefinition对象

BeanDefinition是Bean在实例化过程包装的对象

image-20211128215537489

子类实现父类的抽象方法 -> 这种行为就可以看作是模板设计模式

image-20211128221953302

image-20211128222041250

1 创建XmlBeanDefinitionReader对象

image-20211128222144148

2 通过Reader对象加载配置文件

image-20211128222421663

3 把配置文件封装成Document对象

image-20211130202727099

4 创建BeanDefinitionDocumentReader对象,documentReader负责对document对象解析

image-20211130202939708

5 标签解析

标签解析分为常规标签解析自定义标签解析

image-20211130203310758

5.1常规标签解析(默认标签 parseDefaultElement()方法)

image-20211130203657363

5.1.1 import 标签解析(importBeanDefinitionResource)

5.1.2 Alias 标签解析 processAliasRegistration

5.1.3 Bean 标签解析 processBeanDefinition(重点)

image-20211130204943862

image-20211130205054410

  1. 创建 GenericBeanDefinition 对象
  2. 解析 bean 标签的属性,并把解析出来的属性设置到 BeanDefinition 对象中
  3. 解析 bean 中的 meta 标签
  4. 解析 bean 中的 lookup-method 标签(LookupOverride)
  5. 解析 bean 中的 replaced-method 标签(ReplaceOverride)
  6. 解析 bean 中的 constructor-arg 标签
  7. 解析 bean 中的 property 标签(通过 BeanDefinition 中的 MutablePropertyValues 此类中有List<PropertyValue> propertyValueList 集合来封装<property></property> 对象)

    image-20211130205642802

image-20211130205750856

  1. 解析bean中的qualifier标签
  2. 解析后封装成BeanDefinitionHolder,里面放置beanName和beanDefinition对象。
    beanDefinitionMap是用来放置beanDefinition对象。
    beanDefinitionNames用来放置beanName,bean实例化的时候会用到,并且有排序作用

image-20211130210436276

image-20211130210505741

image-20211130210140089

5.1.4 Beans doRegisterBeanDefinitions递归

image-20211130210912014

image-20211130210939904

image-20211130211004664

5.2 自定义标签解析(parseCustomElement()以componentScan标签为例)

5.2.1 获取自定义标签的namespace命令空间,列如:http://www.sringframework.org/shcema/context

5.2.2 根据命令空间获取NamespaceHandler对象(通过SPI机制获取spring中所有jar包中的META-INF/spring.handlers文件,并建立映射关系)

image-20211202203848260

5.2.3 反射获取NamespaceHandler实例

5.2.4 调用对应标签如ContextNameHandler标签的init()方法

image-20211202205102968

eg:init()

image-20211202215054197

eg:component-scan 和 ComponentScanBeanDefinitionParser对象会存放到Map<String, BeanDefinitionParser> parsers = new HashMap<>()容器中

image-20211202221021205

每个NameHander的init()方法注册不同标签对应的不同的Parse解析器,如:ComponentScanBeanDefinitionParser

image-20211202214939815

5.2.5 调用handler.parse()方法完成解析

如:CompentScan标签解析

此时会根据属性名(eg:component-scan)从Map<String, BeanDefinitionParser> parsers = new HashMap<>()容器中获取解析对象

image-20211202220457302

image-20211204133616277

5.2.5.1 获取base-package属性
5.2.5.2 创建注解扫描器configureScanner(扫描所有.class)
5.2.5.2.1 默认扫描过滤器扫描@Component...

如果use-default-filters为true

默认会扫描@Component注解、@Service注解、@Controller注解、@Repository注解。

还会扫描@ManagedBean注解和@Named注解

image-20211204142842661

image-20211204144651041

扫描器中添加需要扫描的注解类型为:Component.class,而@Service注解引用了@Comonent注解,就是@Component注解实现的功能@Service都能实现,@Service是对@Component进一步拓展。(可以理解为继承)。类似的还有@Controller注解、@Repository注解。

image-20211204142353209

上图注释:

This annotation serves as a specialization of {@link Component @Component}, allowing for implementation classes to be autodetected through classpath scanning.

这个注释充当了{@link Component @Component}的专门化,允许通过类路径扫描自动检测实现类。

5.2.5.2.2 扫描过滤器中添加include-filter和exclude-filter

image-20211204153342172

5.2.5.3 scanner.doScan()->扫描装箱BeanDefinition对象

通过层层递归扫描 base-package 下的包,先扫描出 classpath:/base-package 以.class 结尾的所有文件,然
后再根据过滤器扫描出具有@Service 和@Component 注解的类添加到对应的集合 Set<BeanDefinition>完成
BeanDefinition 的注册。

image-20211204154858283

image-20211204154611165

image-20211204155107310

5.2.5.3 registerComponents()中注册了几个重要的后置类

如 :

ConfigurationClassPostProcessor (会扫描@Configuration @Component @Bean 注解的解析)

AutowiredAnnotationBeanPostProcessor (会扫描@Value 和@Autowired 注解)

CommonAnnotationBeanPostProcessor (会扫描@PostConstruct 和@PreDestroy注解)

image-20211204160320914

image-20211204161301264

6 BeanDefinition缓存到容器

最终解析的标签封装成BeanDefinition对象,并缓存到容器中

原文地址:https://www.cnblogs.com/doagain/p/15635680.html