Spring源码- context:component-scan base-package标签的作用源码解析

1.扫描包路径下所有的类加载解析成bean定义信息
在这里插入图片描述
ClassPathBeanDefinitionScanner .doScan方法调用路径

doScan:276, ClassPathBeanDefinitionScanner (org.springframework.context.annotation)
parse:95, ComponentScanBeanDefinitionParser (org.springframework.context.annotation)
parse:76, NamespaceHandlerSupport (org.springframework.beans.factory.xml)
parseCustomElement:1475, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseCustomElement:1452, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseBeanDefinitions:181, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
doRegisterBeanDefinitions:150, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:97, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:526, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:397, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:341, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:190, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:234, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:197, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:267, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:150, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:102, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:138, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:718, AbstractApplicationContext (org.springframework.context.support)
refresh:577, AbstractApplicationContext (org.springframework.context.support)
<init>:150, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:98, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:15, MyClassPathXmlApplicationContext (com.mashibing)
main:84, Test (com.mashibing)

parse:95, ComponentScanBeanDefinitionParser (org.springframework.context.annotation)

解析节点使用scanner在执行的basePackages包中执行扫描,返回已注册的bean定义

	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
   
   
		// 获取<context:component-scan>节点的base-package属性值
		String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);//base-package
		// 解析占位符
		basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
		// 解析base-package(允许通过,;\t\n中的任一符号填写多个)
		String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
				ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

		// Actually scan for bean definitions and register them.
		// 构建和配置ClassPathBeanDefinitionScanner
		ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);//类路径Bean定义扫描器
		// 使用scanner在执行的basePackages包中执行扫描,返回已注册的bean定义
		Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
		// 组件注册(包括注册一些内部的注解后置处理器,触发注册事件)
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}

doScan:276, ClassPathBeanDefinitionScanner (org.springframework.context.annotation)

扫描开始

	/**
	 * Perform a scan within the specified base packages, 在指定的基本包内执行扫描,
	 * returning the registered bean definitions. 返回已注册的bean定义。
	 * <p>This method does <i>not</i> register an annotation config processor 这个方法不注册注释配置处理器
	 * but rather leaves this up to the caller. 而是把这个问题留给调用者。
	 * @param basePackages the packages to check for annotated classes 要检查带注释的类的包
	 * @return set of beans registered if any for tooling registration purposes (never {@code null}) 为了工具注册目的而注册的bean集(从不{@code null})
	 */
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   
   
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		// 遍历basePackages
		for (String basePackage : basePackages) {
   
   
			// 扫描basePackage,将符合要求的bean定义全部找出来
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			// 遍历所有候选的bean定义
			for (BeanDefinition candidate : candidates) {
   
   
				// 解析@Scope注解,包括scopeName和proxyMode
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				// 使用beanName生成器来生成beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
   
   
					// 处理beanDefinition对象,例如,此bean是否可以自动装配到其他bean中
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
   
   
					// 处理定义在目标类上的通用注解,包括@Lazy,@Primary,@DependsOn,@Role,@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查beanName是否已经注册过,如果注册过,检查是否兼容
				if (checkCandidate(beanName, candidate)) {
   
   
					// 将当前遍历bean的bean定义和beanName封装成BeanDefinitionHolder
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					// 根据proxyMode的值,选择是否创建作用域代理
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolde
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值