Spring框架IOC容器初始化核心源码解析之三:BeanDefinition注册

详细分析了spring是如何找到并解析配置类,如果将通过@ComponentScan 和 @Component 、@Bean 以及 @Import 注解声明的bean,自动注册的容器中的。

用于debug的源码:https://gitee.com/cq-laozhou/spring-stack-source-code-analysis

invokeBeanFactoryPostProcessors 步骤解析

本篇接着上篇,解析refresh方法中的 invokeBeanFactoryPostProcessors(beanFactory) 这个步骤,该方法会调用到 PostProcessorRegistrationDelegate的 invokeBeanFactoryPostProcessors 方法上, 这个方法就是来回调 BeanDefinitionRegistryPostProcessors 以及 BeanFactoryPostProcessor 的。
整体逻辑是:

  1. 调用通过 context.addBeanFactoryPostProcessor 加到容器中的 BeanDefinitionRegistryPostProcessor
  2. 调用实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
  3. 调用实现了Ordered的 BeanDefinitionRegistryPostProcessor
  4. 调用常规的 BeanDefinitionRegistryPostProcessor ,通过循环解决BeanDefinitionRegistryPostProcessor又加入新的BeanDefinitionRegistryPostProcessor的情况。
  5. =====================
  6. 把所有的 BeanDefinitionRegistryPostProcessor 当做 BeanFactoryPostProcessor 调用
  7. 调用通过 context.addBeanFactoryPostProcessor 加到容器中的 BeanFactoryPostProcessor
  8. 调用实现了 PriorityOrdered 的 BeanFactoryPostProcessor
  9. 调用实现了Ordered的 BeanFactoryPostProcessor
  10. 调用常规的 BeanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        
        
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		//processedBeans用于保存已经调用过的beanName,防止重复调用。
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//常规的BeanFactoryPostProcessor,里面放的是通过context.addBeanFactoryPostProcessor加入的BeanFactoryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			//里面存放所有的 BeanDefinitionRegistryPostProcessor 
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            //通过context.addBeanFactoryPostProcessor加入的进行区分,并且如果是BeanDefinitionRegistryPostProcessor则先调用。
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			//当前的 BeanDefinitionRegistryPostProcessor 的待调用列表,会随着调动过程清除和加入。
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            //从容器中获取所有 实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors。并放到当前待调用的列表中。
			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				    //beanFactory.getBean方法是从容器中获取bean实例,这个方法会在后面单独说明。
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			//对当前待调用列表排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			
			//当前待调用的 BeanDefinitionRegistryPostProcessors 加入到 registryProcessors中
			registryProcessors.addAll(currentRegistryProcessors);
			
			//依次调用待调用列表中所有BeanDefinitionRegistryPostProcessors
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			
			//清除当前待调用列表
			currentRegistryProcessors.clear();

            //从容器中获取所有 实现了Ordered的BeanDefinitionRegistryPostProcessors。并放到当前待调用的列表中。
			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			//对当前待调用列表排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//当前待调用的 BeanDefinitionRegistryPostProcessors 加入到 registryProcessors中
			registryProcessors.addAll(currentRegistryProcessors);
			//依次调用待调用列表中所有BeanDefinitionRegistryPostProcessors
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清除当前待调用列表
			currentRegistryProcessors.clear();


            //最后,调用常规的 BeanDefinitionRegistryPostProcessors 。这儿和前面有点区别是,使用了循环来解决在 BeanDefinitionRegistryPostProcessors 中又注册了一个新的 BeanDefinitionRegistryPostProcessors 进去,确保所有的BeanDefinitionRegistryPostProcessors都会被正常调用。
			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
			    //调用常规的逻辑和前面的两种是一样的。
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}
            
            //当所有的 BeanDefinitionRegistryPostProcessors 都被正常调用过后,就可以调用BeanFactoryPostProcessor 了
            
            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            //首先依次调用所有 BeanDefinitionRegistryPostProcessors的postProcessBeanFactory方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			
			//然后调用通过context.addBeanFactoryPostProcessor加入的BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}


        //从容器中欧获取所有 BeanFactoryPostProcessor 的beanName。
		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        //遍历所有的BeanFactoryPostProcessor,并分到三个List中去,分别为实现了PriorityOrdered,实现了Ordered 以及 其他的。
		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
			    //前面已经处理过了,直接跳过。
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

        //遍历调用 priorityOrderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        //遍历调用 orderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        //遍历调用 nonOrderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

遍历调用 BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry的代码:

private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

遍历调用 BeanFactoryPostProcessor的 postProcessBeanFactory 的代码:

private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}

现在,我们知道spring是如何调用 BeanDefinitionRegistryPostProcessors 和 BeanFactoryPostProcessor的。
结合上一篇文章,我们知道,在初始化AnnotatedBeanDefinitionReader中,会注册一些内部的spring组件到容器中,其中第一个注册的是 ConfigurationClassPostProcessor,它是一个BeanDefinitionRegistryPostProcessor,因此它会被调用。

ConfigurationClassPostProcessor

ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法非常重要,所有我们声明的bean,都是由它将beandefinition加载到容器中的:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	    ....
	    //处理配置声明的beandefinition。
		processConfigBeanDefinitions(registry);
	}

而 processConfigBeanDefinitions 方法主要是构建ConfigurationClassParser实例,然后使用循环多轮解析的方式来解析配置类,加载配置类中声明的bean定义到容器中:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        //存放配置类的beandefinition
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		
		String[] candidateNames = registry.getBeanDefinitionNames();
        
        //这段代码就是从spring容器中找出配置类的beandefinition,放入到configCandidates中。
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			//忽略一些健壮性处理的代码
			......
			 if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}
        
        //忽略不影响理解的代码
		.......

        //这段代码是对bean名称生成器的设置,当用户指定了名称生成器就用用户指定的,否则使用默认的。
		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}
        
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

        //构建 ConfigurationClassParser 实例,这个类用来解析配置类。
		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);


        //candidates 用于保存当前这一轮解析的配置类定义
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		
		//alreadyParsed 用于保存已经解析配置类信息
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		
		//注意这个循环,使用多轮解析的方式,来解决新注册进来的bean中,又有能够当做配置类的情况【注意一点的是,并不只是@Configuration的类才是配置类,有@Component @ComponentScan @Import @ImportResource @Bean方法 的类都可以当做配置类】。
		do {
		    //真正解析当前这一轮的配置。注意@ComponentScan 扫描的beandefinition在 parse 中就已经注册到容器中了
			parser.parse(candidates);
			//验证
			parser.validate();

            //ConfigurationClassParser中所有已经解析的配置类信息,然后去除已经解析的,剩下的就是当前这一轮新解析的配置类。
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			//加载这一轮新解析的配置类中的beandefinition,注意这儿加载的是配置类本身会作为beandefinition注册,它里面的 @Bean方法 也会注册,还会调用通过@Import定义的 ImportBeanDefinitionRegistrar 。
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
            
            //清空当前这一轮的解析的配资类定义。
			candidates.clear();
			
			//这儿通过容器中的beandefinition数量和原来的数量,来判断是否有新的beandefinition注册进来。
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				
				//这段代码是判断新注册进来的beandefinition中,没有被当做配置类解析过,并且如果可以当做配置类(注意spring内分为全配置类full-使用@Configuration,轻配置类lite-使用@Component,@ComponentScan @Import,@ImportSource,甚至于类中有@Bean注解的方法,这些类都会被当做配置类处理),就加入到新一轮的待解析candidates中。
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		//如果还要待解析的配置类,继续解析。
		while (!candidates.isEmpty());
        
        //忽略
		....
	}

ConfigurationClassParser

接下来看看 ConfigurationClassParser.parse 方法,主要是遍历解析传入的配置类beandefinition

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		
        //遍历解析传入的配置类beandefinition
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
			....
		}
	}

调用 processConfigurationClass方法,这个方法主要是循环递归解析当前配置类,以及该配置类的超类。

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		...

        //循环递归解析当前配置类,以及该配置类的超类。
		// 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);
	}

核心的解析代码位于 doProcessConfigurationClass 方法中:

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		//处理 @PropertySource 注解
		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			...
		}

        //重要!! 处理  @ComponentScan 注解,扫描的bean就是在这儿被注册到容器中的。
		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			
			for (AnnotationAttributes componentScan : componentScans) {
			    
			    //如果配置类中有 @ComponentScan 注解,立即扫描并注册。
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				
				//检查扫描注册的beandefinition中,如果可以当做配置类(注意spring内分为全配置类full-使用@Configuration,轻配置类lite-使用@Component,@ComponentScan @Import,@ImportSource,甚至于类中有@Bean注解的方法,这些类都会被当做配置类处理),则递归解析。
				// 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());
					}
				}
			}
		}

        //重要!! 处理 @Import 注解
		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), true);

        ...
    
        //重要!! 处理 @Bean  注解方法。将@Bean注解的方法解析出来,加到configClass中。
		// Process individual @Bean methods
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);

        //如果有父类,则返回父类的class,这回导致其调用方法processConfigurationClass循环不会退出,将其父类当做配置类,继续解析。
		// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());这行代码中,会调用ComponentScanAnnotationParser.parse 方法,该方法主要是实例化ClassPathBeanDefinitionScanner,并设置相关的属性,比如basePackages、includeFilters、excludeFilters ,最后调用真正干活的doScan方法:

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		
		//实例化 ClassPathBeanDefinitionScanner 。
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

		....

		scanner.setResourcePattern(componentScan.getString("resourcePattern"));

        //设置includeFilters
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addIncludeFilter(typeFilter);
			}
		}
		//设置 excludeFilters
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addExcludeFilter(typeFilter);
			}
		}

		...
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

doScan方法,真正的扫描,过滤,最后注册满足的beandefinition。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		
		//扫描并注册的beandefinition
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
		    //找到候选的beandefinition 
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			
			//遍历找到到beandefinition,检查通过后注册到容器中。
			for (BeanDefinition candidate : candidates) {
				...
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			    ...
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//注册
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

继续看findCandidateComponents方法,发现它会调用scanCandidateComponents方法,这个方法才是真正做扫描工作的:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        //扫描到的spring组件。
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
		    //构建扫描路径
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//扫描路径下的类都解析为Resource。
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			
			//遍历所有的类,如果是spring组件,则添加到candidates中。
			for (Resource resource : resources) {
				
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						
						//判断当前类是不是候选spring组件
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
							if (isCandidateComponent(sbd)) {
								candidates.add(sbd);
							}
						 }
				    }
				}
			}
		}
		return candidates;
	}

其中 isCandidateComponent方法中就应用了excludeFilters和includeFilters,结合上一文中,ClassPathBeanDefinitionScanner实例化时,会注册默认的includeFilters,加入载@Component,这就是默认@ComponetScan会加载@Component的原理了。

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}

分析到这儿,通过@ComponentScan + @Component 这种方式就分析得差不多了。@Bean的处理相对简单,在 doProcessConfigurationClass 方法中,已经将有@Bean注解的方法解析出来放到ConfigurationClass中了,在一轮解析完成后,有一步this.reader.loadBeanDefinitions(configClasses);调用,它里面包含来注册 @Bean 方法声明的beandefinition:

private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
        ....
        //注册@import的类为beandefinition,当做配置类时,要注册到容器中。
		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		
		//注册@Bean声明的beandefinition。
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
        
        //注册ImportedResources的
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		
		//调用@@import中,指定的类为ImportBeanDefinitionRegistrar时
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

跟进去看loadBeanDefinitionsForBeanMethod方法:

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
		MethodMetadata metadata = beanMethod.getMetadata();
		String methodName = metadata.getMethodName();

		...
        //获取@Bean注解信息
		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
		
		//beanName默认是方法名的代码
		// Consider name and any aliases
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		// Register aliases even when overridden
		for (String alias : names) {
			this.registry.registerAlias(beanName, alias);
		}

		//初始化BeanDefinition
		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
		
		//设置BeanDefinition属性
		beanDef.setResource(configClass.getResource());
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

		....

		String initMethodName = bean.getString("initMethod");
		if (StringUtils.hasText(initMethodName)) {
			beanDef.setInitMethodName(initMethodName);
		}

		String destroyMethodName = bean.getString("destroyMethod");
		beanDef.setDestroyMethodName(destroyMethodName);

	    ...
        //注册beandefinition
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}

@Import的解析因为分3中情况,相对来说复制一下,不过核心思路是:

  1. 解析处理@Import注解的所有value指定的类。
  2. 遍历value指定的类,
    • 如果是ImportSelector,则调用其selectImports方法,将结果当做value指定的类,递归解析@Import注解。
    • 如果结果是ImportBeanDefinitionRegistrar,则放到configClass中。
    • 如果不是ImportSelector和ImportBeanDefinitionRegistrar,则当做配置类处理,递归解析配置类

因此,@Import注解指定的类,通常是用来指定配置类的。

看下处理@Import直接的方法 processImports :

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
        
        //遍历候选的import类
    	for (SourceClass candidate : importCandidates) {
    	
    	    //如果是ImportSelector,实例化,并调用方法,获取结果递归调用 processImports。
    		if (candidate.isAssignable(ImportSelector.class)) {
    			// Candidate class is an ImportSelector -> delegate to it to determine imports
    			Class<?> candidateClass = candidate.loadClass();
    			ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
    			ParserStrategyUtils.invokeAwareMethods(
    					selector, this.environment, this.resourceLoader, this.registry);
    			....
    			//调用selectImports方法,将返回结果传入当前方法,递归调用processImports
				String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
				Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
				processImports(configClass, currentSourceClass, importSourceClasses, false);
    			
    		}
    		
    		//如果是ImportBeanDefinitionRegistrar,则实例化后,放到configClass中。
    		else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
    			// Candidate class is an ImportBeanDefinitionRegistrar ->
    			// delegate to it to register additional bean definitions
    			Class<?> candidateClass = candidate.loadClass();
    			ImportBeanDefinitionRegistrar registrar =
    					BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
    			ParserStrategyUtils.invokeAwareMethods(
    					registrar, this.environment, this.resourceLoader, this.registry);
    			configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
    		}
    		
    		//如果都不是,则当做配置类处理,递归调用processConfigurationClass解析配置类。
    		else {
    			// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
    			// process it as an @Configuration class
    			this.importStack.registerImport(
    					currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
    			processConfigurationClass(candidate.asConfigClass(configClass));
    		}
    	}
			
	}

回到 loadBeanDefinitionsForConfigurationClass 方法中:

private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
        ....
        //注册@import的类为beandefinition,当做配置类时,要注册到容器中。
		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		
		//注册@Bean声明的beandefinition。
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
        
        //注册ImportedResources的
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		
		//调用 @@import中,指定的类为ImportBeanDefinitionRegistrar时
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

registerBeanDefinitionForImportedConfigurationClass 和 loadBeanDefinitionsFromRegistrars 的代码简答,你可以自行分析。

到此,我们基本上分析清楚了spring是如何找到并解析配置类,如果将通过@ComponentScan 和 @Component 、@Bean 以及 @Import 注解声明的bean,自动注册的容器中的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值