栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring 如何解析@ComponentScan 源码阅读

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring 如何解析@ComponentScan 源码阅读

@ComponentScan包扫描功能实现

实现过程:

① @ComponentScan 这个注解的作用

作用自己搜索

② spring 如何解析@ComponentScan:

spring的核心模块spring-context中的package org.springframework.context.support中,有个注解解析类ComponentScanAnnotationParser。

ComponentScanAnnotationParser有个方法parse(),这个方法就是用来解析ComponentScan的,

在parse()中定义了ClassPathBeanDefinitionScanner,ClassPathBeanDefinitionScanner scanner

= new ClassPathBeanDefinitionScanner(…); scanner 是扫描器。同时parse()实现对

@ComponentScan的useDefaultFilters、scopedProxy、scopedProxy、scopeResolver、

resourcePattern,includeFilters、excludeFilters、lazyInit、basePackageClasses、basePackages等属

性的访问获取信息生成一个对象,然后给scanner.doScan()使用。

在ClassPathBeanDefinitionScanner主要两个tips:

1、ClassPathBeanDefinitionScanner构造器中的执行的父类的 registerDefaultFilters()方法,在这个方法中this.includeFilters.add(new AnnotationTypeFilter(Component.class)); 添加了带有@Component注解的类。

ClassPathBeanDefinitionScanner的doScan扫描方法中,用registerBeanDefinition(definitionHolder, this.registry)方法注册了bean, definitionHolder, bean的信息持有者,registry注册器。在registerBeanDefinition()方法中调用了BeanDefinitionReaderUtils.registerBeanDefinition()进行bean注册,而这个方法最终使用的是registry进行注册的,代码是这样: registry.registerBeanDefinition(beanName,definitionHolder.getBeanDefinition());

2、registry在哪里:

ConfigurationClassParser类的构造器中使用就是BeanDefinitionRegistry的registry,ConfigurationClassParser下文会介绍。

public ConfigurationClassParser(metadataReaderFactory metadataReaderFactory,
	ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader,
	BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {

this.metadataReaderFactory = metadataReaderFactory;
this.problemReporter = problemReporter;
this.environment = environment;
this.resourceLoader = resourceLoader;
this.registry = registry;
this.componentScanParser = new ComponentScanAnnotationParser(
		environment, resourceLoader, componentScanBeanNameGenerator, registry);
this.conditionevaluator = new Conditionevaluator(registry, environment, resourceLoader);

}

③ ConfigurationClassParser:

位置:

package org.springframework.context.annotation#ConfigurationClassParser

ConfigurationClassParser:这个类为配置类解析器。

这个类型有个方法doProcessConfigurationClass,在这个方法中定义了@ComponentScans信息,
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getmetadata(), ComponentScans.class, ComponentScan.class);

componentScans包含了注解@ComponentScans的各种属性,

然后调用 this.componentScanParser.parse(这个ComponentScanAnnotationParser类的方法parse)
会对各种属性进行分析并执行相应的功能。

具体代码:

// Process any @ComponentScan annotations
		Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getmetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionevaluator.shouldSkip(sourceClass.getmetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getmetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

④ ConfigurationClassParser的registry来源

ConfigurationClassParser构造函数registry

spring核心模块spring-context

包package org.springframework.context.annotation

类:ConfigurationClassPostProcessor#ConfigurationClassParser

public ConfigurationClassParser(metadataReaderFactory metadataReaderFactory,
			ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader,
			BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {

		this.metadataReaderFactory = metadataReaderFactory;
		this.problemReporter = problemReporter;
		this.environment = environment;
		this.resourceLoader = resourceLoader;
		
		
		this.registry = registry;
		
		
		this.componentScanParser = new ComponentScanAnnotationParser(
				environment, resourceLoader, componentScanBeanNameGenerator, registry);
		this.conditionevaluator = new Conditionevaluator(registry, environment, resourceLoader);
	}

spring核心模块spring-context

包package org.springframework.context.annotation

类:ConfigurationClassPostProcessor#processConfigBeanDefinitions

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	int registryId = System.identityHashCode(registry);
	if (this.registriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
	}
	if (this.factoriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + registry);
	}
	this.registriesPostProcessed.add(registryId);

	processConfigBeanDefinitions(registry);
}
**processConfigBeanDefinitions方法**


		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

spring核心模块spring-context

包package org.springframework.context.support

类:PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

private static void invokeBeanDefinitionRegistryPostProcessors(
		Collection postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

	for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
		StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
				.tag("postProcessor", postProcessor::toString);
				
				
				
		postProcessor.postProcessBeanDefinitionRegistry(registry);
		
		
		
		postProcessBeanDefRegistry.end();
	}
}

spring核心模块spring-context

包package org.springframework.context.support

AbstractApplicationContext#invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {


	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	
	

	// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
	// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
	if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

调用过程:

ClassPathXmlApplicationContext实现AbstractApplicationContext

----->AbstractApplicationContext.invokeBeanFactoryPostProcessors()

----->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()

---->ConfigurationClassPostProcessor.processConfigBeanDefinitions()

---->ConfigurationClassParser.ConfigurationClassParser()

---->ConfigurationClassParser() this.registry = registry;

---->ConfigurationClassParser.doProcessConfigurationClass()

---->doProcessConfigurationClass

------>this.componentScanParser.parse()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/759678.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号