spring源码03-xml配置文件conent标签解析流程
本文主要介绍spring的xml配置文件 context:component-scan 配置对应的处理流程,通过该标签的属性配置实现对注解的支持等。对于xml的加载流程,自定义标签的处理流程请看上一篇文章:spring源码02-xml配置文件解析过程
一、content标签支持的localName以及对应的处理类
/*context 标签对应的处理类;ContextNamespaceHandler
下边列出了每个localName对应的实际处理类
例如:component-scan,property-placeholder就是一个个不同的localName
<context:component-scan base-package="xxx"/>
<content:property-placeholder location="xxxx"/>*/
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// properties配置文件加载相关
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
// properties配置重写
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
// 注解的支持@Autowired @Value @Inject,@Resource @PostConstruct @PreDestroy,@Required
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
// 启用对bean的扫描
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
// 下方的没有使用过,不太清楚
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
二、component-scan标签的处理类:ComponentScanBeanDefinitionParser 配置的解析工作
- 配置示例及说明:
<context:component-scan base-package="example.ioc" use-default-filters="true" annotation-config="true">
<context:include-filter type="annotation" expression="example.ioc.MyAnnotation"/>
<context:include-filter type="regex" expression=".*Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--
component-scan 会触发ComponentScanBeanDefinitionParser类对其进行解析,
base-package指定被扫描的类路径,
use-default-filters为true时,支持对Component注解的支持;
include-filter和exclude-filter标签可以根据配置规则实现对类的扫描或忽略;
此标签内的annotation-config属性处理逻辑与<context:annotation-config/>标签对应的处理类AnnotationConfigBeanDefinitionParser实现了相同的逻辑,下方一起说明。
-->
- component-scan标签处理入口:ComponentScanBeanDefinitionParser.parse();
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
//xml配置的属性名称
private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";
private static final String RESOURCE_PATTERN_ATTRIBUTE = "resource-pattern";
private static final String USE_DEFAULT_FILTERS_ATTRIBUTE = "use-default-filters";
private static final String ANNOTATION_CONFIG_ATTRIBUTE = "annotation-config";
private static final String NAME_GENERATOR_ATTRIBUTE = "name-generator";
private static final String SCOPE_RESOLVER_ATTRIBUTE = "scope-resolver";
private static final String SCOPED_PROXY_ATTRIBUTE = "scoped-proxy";
private static final String EXCLUDE_FILTER_ELEMENT = "exclude-filter";
private static final String INCLUDE_FILTER_ELEMENT = "include-filter";
private static final String FILTER_TYPE_ATTRIBUTE = "type";
private static final String FILTER_EXPRESSION_ATTRIBUTE = "expression";
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//获取配置的包扫描路径
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
//对包路径进行转换,完成对${}占位符的替换
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
//多个包路径拆分
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS );
// Actually scan for bean definitions and register them.
//构建类扫描器,是否启动对component注解的支持
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
//对bean对象的扫描,过滤,并注册到beanFactory(用户创建类的注册)
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
//annotation-config解析属性判断是否启用对注解的支持
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
...
}
- configureScanner 方法:构建类扫描器,是否启动对component注解的支持
// ComponentScanBeanDefinitionParser
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
// 是否启动对component注解对支持,默认启动,
// 该值为true会触发对@Component标注的类的注册工作
boolean useDefaultFilters = true;
// 配置文件中的配置
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
// Delegate bean definition registration to scanner class.
// 创建扫描类,构建上下文环境,bean注册器,环境变量,资源加载器
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
// 是否指定了扫描的文件后缀模式,默认为:"**/*.class"
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
// 自定义bean名称生成器
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
try {
parseScope(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
//解析过滤器标签,include,exclude配置,扫描并注册相应的类,或者跳过注册类
parseTypeFilters(element, scanner, parserContext);
return scanner;
}
- createScanner 创建配置扫描对象
//调用的构造方法签名:ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader);
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader());
}
- registerComponents:解析属性annotation-config判断是否启用对注解的支持
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
Object source = readerContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}
// Register annotation config processors, if necessary.
//是否创建Annotation config处理类
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
//注册支持注解所需的处理类,annotation-config标签的支持
Set<BeanDefinitionHolder>
=
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
readerContext.fireComponentRegistered(compositeDef);
}
三、对注解功能的支持
annotation-config处理:AnnotationConfigUtils.registerAnnotationConfigProcessors(), 该方法内注册的三个重要类对象;
//ConfigurationClassPostProcessor 实现BeanFactoryPostProcess,完成对bean定义信息的添加修改等
//AutowiredAnnotationBeanPostProcessor实现BeanPostProcessor,完成对bean对象的属性注入工作
//CommonAnnotationBeanPostProcessor实现BeanPostProcessor,完成对bean对象的属性注入工作,初始化,销毁等工作
1. ConfigurationClassPostProcessor :对Configuration, Component, ComponentScan, Import, ImportResource, Bean等注解的支持
//ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
// 同时实现了BeanFactoryPostProcess接口;
// 触发的方法有两个:postProcessBeanDefinitionRegistry()和postProcessBeanFactory()方法;
// 当前类该方法实现对Configuration, Component, ComponentScan, Import, ImportResource, Bean等注解的支持
BeanDefinitionRegistryPostProcessor:
postProcessBeanDefinitionRegistry();
// 当前类该方法实现对Configuration注解的类进行代理对象的创建;
// 对Configuration类进行代理的作用是为了保证单例对象的单实例,避免多次方法调用产生多个实例;
// 同时该方法内部添加了一个BeanPostProcess--ImportAwareBeanPostProcessor;
BeanFactoryPostProcess:
postProcessBeanFactory();
// ------------------------------------------------------------------------
//ImportAwareBeanPostProcessor实现了SmartInstantiationAwareBeanPostProcessor接口
// 实际重写了以下两个方法postProcessProperties()和postProcessBeforeInitialization();
// 完成对EnhancedConfiguration实现类的BeanFactory的注入;EnhancedConfiguration接口继承了BeanFactoryAware接口需要完成setBeanFactory方法的调用
InstantiationAwareBeanPostProcessor:
postProcessProperties();
// 完成对ImportAware实现类的AnnotationMetadata的属性注入;
BeanPostProcessor:
postProcessBeforeInitialization();
2. AutowiredAnnotationBeanPostProcessor:实现Autowired, Value, Inject等注解的支持
//AutowiredAnnotationBeanPostProcessor 实现了MergedBeanDefinitionPostProcessor,SmartInstantiationAwareBeanPostProcessor接口,同时实现BeanPostProcess接口;
// 重要的方法:postProcessMergedBeanDefinition(),determineCandidateConstructors()和postProcessProperties();
MergedBeanDefinitionPostProcessor:
// 标记所有bean对象中@Autowired @Value @Inject标记的属性、方法;后续属性注入使用
postProcessMergedBeanDefinition();
// spring容器重复添加相同名称的bean定义信息时或移除一个bean定义信息时会触发该方法。移除缓存信息,不具体展开。
resetBeanDefinition();
SmartInstantiationAwareBeanPostProcessor:
// 空方法
predictBeanType();
// 该方法用于查找类构造器方法中是否存在Autowired, Inject的构造方法,bean工厂创建bean对象时调用该方法,获取反射创建对象的构造器方法;
determineCandidateConstructors();
// 空方法
getEarlyBeanReference();
InstantiationAwareBeanPostProcessor:
// 空方法
postProcessBeforeInstantiation();
// 空方法
postProcessAfterInstantiation();
// 通过该方法完成对Autowired, Value, Inject注解属性的属性注入工作
postProcessProperties();
BeanPostProcessor:
// 空方法
postProcessBeforeInitialization();
// 空方法
postProcessAfterInitialization();
3. CommonAnnotationBeanPostProcessor:实现对PostConstruct, PreDestroy, Resource等注解的支持
// CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor类;
// InitDestroyAnnotationBeanPostProcessor类实现了DestructionAwareBeanPostProcessor,MergedBeanDefinitionPostProcessor接口;
// CommonAnnotationBeanPostProcessor同时实现了InstantiationAwareBeanPostProcessor接口;
MergedBeanDefinitionPostProcessor:
// 实现对PostConstruct, PreDestroy, Resource等注解的查找,
postProcessMergedBeanDefinition();
// 同AutowiredAnnotationBeanPostProcessor类实现的该方法,实现相同的功能,只不过清除的缓存对象不同
resetBeanDefinition();
DestructionAwareBeanPostProcessor:
// 对象销毁时调用该方法,通过该方法完成对bean对象PreDestroy注解的自定义销毁方法的调用
postProcessBeforeDestruction();
InstantiationAwareBeanPostProcessor:
// 空方法
postProcessBeforeInstantiation();
// 空方法
postProcessAfterInstantiation();
// 该方法完成对Resource注解属性的属性注入工作
postProcessProperties();
BeanPostProcessor:
// 通过该方法实现对bean对象PostConstruct注解的自定义init方法的调用
postProcessBeforeInitialization();
// 空方法
postProcessAfterInitialization();
邮箱:quiet_learn@163.com
本文版权归作者和博客园共有,欢迎转载,转载请在文章明显位置注明作者及出处,谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2021-03-28 RPC 基本原理