Spring 自动扫描和注解配置类

168 阅读4分钟

注解相关的

自动扫描

xml配置下的

<context:component-scan/>

spring.handler查找到对应的element handlerContextNamespaceHandler,parser:ComponentScanBeanDefinitionParser

类解析ComponentScanBeanDefinitionParser

//ComponentScanBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
	String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
			ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

	// Actually scan for bean definitions and register them.
	ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
	//扫描并注册
	Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
	registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

	return null;
}

protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
    XmlReaderContext readerContext = parserContext.getReaderContext();

    boolean useDefaultFilters = true;
    if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
        useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
    }

    // Delegate bean definition registration to scanner class.,设置<beans>上的一些参数给scanner
    ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);
    scanner.setResourceLoader(readerContext.getResourceLoader());
    scanner.setEnvironment(parserContext.getDelegate().getEnvironment());
    scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
    scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());

    if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
        scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
    }

    try {
        //自动扫描类名称生成器
        parseBeanNameGenerator(element, scanner);
    } catch (Exception ex) {
        readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());
    }

    try {
        //处理scope注解和scope解析器
        parseScope(element, scanner);
    } catch (Exception ex) {
        readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());
    }
    //设置type过滤器
    parseTypeFilters(element, scanner, readerContext, parserContext);

    return scanner;
}

ComponentScan是自动扫描class文件生成beanDefinition,那么该类肯定会提供设置beanDefinition相关属性的功能.包括scope,nameGenerator,类过滤器等.

<context:component-scan base-package="" resource-pattern="" annotation-config="" scoped-proxy=""/>

其中resource-pattern设置class的匹配模式,使用的是ant分隔,baseDirbase-package指定.

componentScanner将扫描出来的resource封装成SimpleMetadataReader来进行过滤判断.

SimpleMetadataReader 内部实际上使用asmclass文件解析成一个class信息树.

ClassPathBeanDefinitionScanner 内部定义的beanNameGenerator(AnnotationBeanNameGenerator)ScopeMetadataResolver(AnnotationScopeMetadataResolver) 默认支持继承@Component@Scopse注解, 自定义的@Component 支持value属性.因为componentScanner 扫描出来的beanDefinitonScannedGenericBeanDefinition,本身继承AnnotatedBeanDefinition.

注解启用

<context:componentscan/>可以在解析该节点的时候就扫描所有的component,但是使用注解处理的情况下会这么办.是在合适执行扫描操作呢.是什么时候处理该注解的呢?

ConfigurationClassPostProcessor 处理@Configuration注解

ConfigurationClassPostProcessor 继承 BeanDefinitionRegistryPostProcessor,

BeanDefinitionRegistryPostProcessor 继承 BeanFactoryPostProcessor ,

这两个接口本质上一样(都是在所有的beanDefinition 加载完成后再次对BeanFactoryBeanDefinitionRegistry进行二次处理). 只是执行先后顺序不一样.

因为ConfigurationClassPostProcessor的作用是加载新的BeanDefinition,所有默认应该实现 BeanDefinitionRegistryPostProcessor 的方法.


@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
  
    //注册 ImportAwareBeanPostProcessor 的BeanPostProcessor
	RootBeanDefinition iabpp = new RootBeanDefinition(ImportAwareBeanPostProcessor.class);
	iabpp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(IMPORT_AWARE_PROCESSOR_BEAN_NAME, iabpp);

	RootBeanDefinition ecbpp = new RootBeanDefinition(EnhancedConfigurationBeanPostProcessor.class);
	ecbpp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(ENHANCED_CONFIGURATION_PROCESSOR_BEAN_NAME, ecbpp);
    //重复执行检测
	int registryId = System.identityHashCode(registry);
	if (this.registriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanDefinitionRegistry already called for this post-processor against " + registry);
	}
	if (this.factoriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called for this post-processor against " + registry);
	}
	this.registriesPostProcessed.add(registryId);
    //核心处理方法
	processConfigBeanDefinitions(registry);
}


public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>();
	//遍历所有的beanDefinition
	for (String beanName : registry.getBeanDefinitionNames()) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		//是否已经处理过改beanDefinition
		if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
				ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
			}
		}
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
		    //如果是候选类,
		    //full候选类, 有@Configuration注解的
		    //lite 带有@Import , @Component , 有@Bean方法的.(那几乎是所有的BeanDefintion都满足)
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}

	// Return immediately if no @Configuration classes were found
	//如果没有立即返回
	if (configCandidates.isEmpty()) {
		return;
	}

	// Detect any custom bean name generation strategy supplied through the enclosing application context
	//探测手动注册的BeanNameGenerator单例(名称固定)
	SingletonBeanRegistry singletonRegistry = null;
	if (registry instanceof SingletonBeanRegistry) {
		singletonRegistry = (SingletonBeanRegistry) registry;
		if (!this.localBeanNameGeneratorSet && singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
			BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
			this.componentScanBeanNameGenerator = generator;
			this.importBeanNameGenerator = generator;
		}
	}

	// Parse each @Configuration class
	ConfigurationClassParser parser = new ConfigurationClassParser(
			this.metadataReaderFactory, this.problemReporter, this.environment,
			this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	//核心解析方法.
	parser.parse(configCandidates);
	parser.validate();

	// Handle any @PropertySource annotations
	List<PropertySource<?>> parsedPropertySources = parser.getPropertySources();
	if (!parsedPropertySources.isEmpty()) {
		if (!(this.environment instanceof ConfigurableEnvironment)) {
			logger.warn("Ignoring @PropertySource annotations. " +
					"Reason: Environment must implement ConfigurableEnvironment");
		}
		else {
			MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
			for (PropertySource<?> propertySource : parsedPropertySources) {
				envPropertySources.addLast(propertySource);
			}
		}
	}

	// Read the model and create bean definitions based on its content
	if (this.reader == null) {
		this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor,
				this.problemReporter, this.metadataReaderFactory, this.resourceLoader, this.environment,
				this.importBeanNameGenerator);
	}

	this.reader.loadBeanDefinitions(parser.getConfigurationClasses());

	// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
	if (singletonRegistry != null) {
		if (!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}
	}

	if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
		((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
	}
}

ConfigurationClassParser.parse

//org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
	for (BeanDefinitionHolder holder : configCandidates) {
		BeanDefinition bd = holder.getBeanDefinition();
		try {
		    //遍历循环每一个类,并解析
			if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
			//存在class的直接解析class,反射
				parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
			}
			else {
			   //否则通过className来解析(asm),
				parse(bd.getBeanClassName(), holder.getBeanName());
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("Failed to load bean class: " + bd.getBeanClassName(), ex);
		}
	}
	processDeferredImportSelectors();
}


protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}
    
    //同一个configuration类被多次处理,可能原因通过import导入的
	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		if (configClass.isImported()) {
			if (existingClass.isImported()) {
				existingClass.mergeImportedBy(configClass);
			}
			// Otherwise ignore new imported config class; existing non-imported class overrides it.
			return;
		}
		else {
			// Explicit bean definition found, probably replacing an import.
			// Let's remove the old one and go with the new one.
			this.configurationClasses.remove(configClass);
			for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext(); ) {
				if (configClass.equals(it.next())) {
					it.remove();
				}
			}
		}
	}

	// Recursively process the configuration class and its superclass hierarchy.
	SourceClass sourceClass = asSourceClass(configClass);
	do {
	    //核心处理方法
		sourceClass = doProcessConfigurationClass(configClass, sourceClass);
	}
	while (sourceClass != null);

	this.configurationClasses.put(configClass, configClass);
}

//一见庐山真面目了
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
	// recursively process any member (nested) classes first
	processMemberClasses(configClass, sourceClass);

	// process any @PropertySource annotations
	//处理property资源文件的导入
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {
		processPropertySource(propertySource);
	}

	// process any @ComponentScan annotations
	AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);
	if (componentScan != null) {
		// the config class is annotated with @ComponentScan -> perform the scan immediately
		if (!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

			// check the set of scanned definitions for any further config classes and parse recursively if necessary
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
			    //处理扫描出来的@configuration类
				parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

	// process any @Import annotations
	//处理导入的configuration类
	processImports(configClass, sourceClass, getImports(sourceClass), true);

	// process any @ImportResource annotations
	//处理xml配置文件
	if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
		AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		String[] resources = importResource.getStringArray("value");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// process individual @Bean methods
	//处理bean
	Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// process superclass, if any
	//获取父类,asm不能获取所有的,所以标准的StandardAnnotationMetadata也没有处理父类的方法
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
			this.knownSuperclasses.put(superclass, configClass);
			// superclass found, return its annotation metadata and recurse
			try {
				return sourceClass.getSuperClass();
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(ex);
			}
		}
	}

	// no superclass, processing is complete
	return null;
}

处理加载资源文件,加载beandefinition等功能外, ConfigurationClassPostProcessor 也 会将 对应的Configuration Beandefinition 进行增强。

ContextAnnotationAutowireCandidateResolver

处理@Lazy

工具类

  1. AnnotationMetadata: 类注解元数据信息类. 实现有StandardAnnotationMetadata(使用class反射) 和 使用asm读取class文件,直接解析的AnnotationMetadataReadingVisitor