解析xml配置文件、java注解类、java配置类为BeanDefinition
一、解析xml配置文件
Xml配置读取器
-
BeanDefinitionReaderXmlBeanDefinitionReader
-
读取文件名称、
Resource抽象,将其解析为Document-
DocumentLoader文档加载器
-
-
读取
Document里的信息,将其解析成BeanDefinition,并注册到IoC容器中BeanDefinitionDocumentReader
xml解析.png
- 委派
BeanDefinitionParserDelegate去解析xml元素和属性- 支持默认和自定义命名空间
- 默认命名空间url:http://www.springframework.org/schema/beans
- 其他均为自定义命名空间
-
NamespaceHandlerResolver命名空间解析器-
DefaultNamespaceHandlerResolver加载META-INF/spring.handlers文件中声明的命名空间处理器
-
-
NamespaceHandler命名空间处理器
- 支持默认和自定义命名空间
BeanDefinitionParserDelegate.png
-
GenericBeanDefinition -
NamespaceHandler命名空间处理器
NamespaceHandler.png
-
支持对自定义元素的解析
-
增强默认元素功能,装饰器模式,通过解析自定义元素、属性的方式进行装饰
(1)如下图
p命名空间,即为装饰bean元素,解析器为:SimplePropertyNamespaceHandler命名空间解析器类声明在
META-INF/spring.handlers文件内,可通过查找该文件定位解析器类<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="s5BeanDemo1" class="org.example.s5.S5BeanDemo1" p:attr1="a1" p:attr2="a2"/> </beans>(2)如下图
aop:scoped-proxy元素,通过定义aop命名空间解析器对<bean>进行增强:AopNamespaceHandler<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="s5BeanDemo2" class="org.example.s5.S5BeanDemo2"> <!-- 装饰 --> <aop:scoped-proxy proxy-target-class="true"/> </bean> </beans>解析<bean>元素源码如下:
// DefaultBeanDefinitionDocumentReader#processBeanDefinition protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 解析元素 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // 装饰元素 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
二、扫描类路径
扫描类路径,通过过滤条件筛选出候选类
TypeFilter 过滤器接口
默认注解过滤器AnnotationTypeFilter支持的注解
- @Component
- @ManagedBean
- @Named
ConditionEvaluator 候选条件评估器
- @Conditional
ClassPathBeanDefinitionScanner 扫描器
-
扫描类路径下的文件
-
使用索引@Indexed获取候选类
-
处理通用注解
- AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition)
- @Lazy
- @Primary
- @DependsOn
-
注册注解配置处理器
- AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry)
-
ConfigurationClassPostProcessor处理@Configuration
-
ScannedGenericBeanDefinition
示例
private static void s5_1() {
final DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
final ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(defaultListableBeanFactory);
final int count = classPathBeanDefinitionScanner.scan("org.example.service.s5");
log.info("加载数量【{}】", count);
final String[] beanDefinitionNames = defaultListableBeanFactory.getBeanDefinitionNames();
log.info("[{}]", Arrays.toString(beanDefinitionNames));
}
三、解析java配置类
AnnotatedBeanDefinitionReader
AnnotatedGenericBeanDefinition- 注册注解配置处理器
- AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry)
-
ConfigurationClassPostProcessor处理@Configuration
四、解析@Configuration配置类
在前三种解析方式中,都可以支持解析配置类,这种方式是通过扩展IoC容器生命周期接口实现的
ConfigurationClassPostProcessor
- 解析配置类
- 条件装配
ConfigurationClassPostProcessor.png
步骤
-
读取IoC容器中所有注册的
BeanDefinition -
筛选出配置类的
BeanDefinition,通过读取元数据,将其解析为ConfigurationClass列表ConfigurationClassParser
-
读取
ConfigurationClass中的信息,构建成BeanDefinition列表,注册到IoC容器中ConfigurationClassBeanDefinitionReader
解析流程
解析流程.png
读取流程
读取注册.png
建议
在@Configuration类中定义@Bean方法创建BeanFactoryPostProcessor时,使用static限定符,避免配置类被过早地实例化








网友评论