spring源码03-xml配置文件conent标签解析流程

发布时间 2023-03-28 15:27:49作者: 铵铵静静

本文主要介绍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 配置的解析工作

  1. 配置示例及说明:
<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实现了相同的逻辑,下方一起说明。
-->
  1. 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;
    }
    ...
}
      
  1. 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;
} 
  1. 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());
	}
  1. 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(); 
  1. 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();
  1. 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();