spring 源码执行BFPP invokeBeanFactoryPostProcessors-ConfigurationClassPostProcessor (2)

上篇传送门
上篇介绍了component-scan标签的解析,把扫描到的@Component类文件扫描到,然后生成bean定义信息并注册到工厂,工厂注册完后,又注册了注解解析内部定义信息(后置处理器)以及监听器,接下来咱们继续看下是如何执行后置处理器的

了解ConfigurationClassPostProcessor之前,先看下关系图,实现了BDRPP、BFPP、PriorityOrdered接口,看到这里都会想到是在哪里进行处理了
在这里插入图片描述
咱们上篇了解到spring只是注册了bean的定义信息,对于internal*对应的类并没有进行实例化,那执行BFPP的时候就必须先创建出bean对象(后面咱们会详细聊,这里先不展开),然后进行调用

文章知识点

  1. 注解什么时候解析的
  2. BDRPP处理了哪些注解
  3. 注解标注的类实例化了吗

PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors 执行BDRPP

private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
	for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
		//执行对应的接口方法
		postProcessor.postProcessBeanDefinitionRegistry(registry);
	}
}
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry 执行模板方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	//记录符合条件的bean定义信息包装类
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	//获取所有的bean定义信息
	String[] candidateNames = registry.getBeanDefinitionNames();
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		//判断是否已经当作配置类处理过
		if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
			}
		// 检查是否符合条件
		// 规则:@Component、@ComponentScan、@Import、@ImportResource、@Bean修饰的bean定义
		}else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}
	// 如果没有符合条件的,直接返回了,说明这个项目比较老,基本是依靠xml方式配置的
	if (configCandidates.isEmpty()) {
		return;
	}
	// checkConfigurationClassCandidate方法进行判断的时候最后进行order值获取,并赋值了,这里进行排序
	configCandidates.sort((bd1, bd2) -> {
		int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
		int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
		return Integer.compare(i1, i2);
	});
	// Detect any custom bean name generation strategy supplied through the enclosing application context
	SingletonBeanRegistry sbr = null;
	// 这里的registry默认是DefaultListableBeanFactory
	// 不了解类关系的 可以查下前面文章,spring大体了解 https://blog.csdn.net/xiaomengxin521/article/details/123277648
	if (registry instanceof SingletonBeanRegistry) {
		sbr = (SingletonBeanRegistry) registry;
		// 如果不存在自定义bean名称生成器
		if (!this.localBeanNameGeneratorSet) {
			// 尝试获取并设置
			BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
			if (generator != null) {
				this.componentScanBeanNameGenerator = generator;
				this.importBeanNameGenerator = generator;
			}
		}
	}
	//保证环境信息(后面会对咱们的占位符进行赋值)
	if (this.environment == null) {
		this.environment = new StandardEnvironment();
	}

	// 创建一个解析对象
	ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	// 定义一个容器,用于存放解析出来的bean定义信息
	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
	//用于存储已经解析过的对象
	Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
	do {
		// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的Bean定义信息
		parser.parse(candidates);
		parser.validate();
		// 存储解析的bean定义信息
		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());
		}
		// 注册bean定义信息到工厂,方便实例化
		this.reader.loadBeanDefinitions(configClasses);
		alreadyParsed.addAll(configClasses);

		candidates.clear();
		// 如果新注册了bean定义信息
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			// 获取解析加载后的bean定义信息
			String[] newCandidateNames = registry.getBeanDefinitionNames();
			// 加载之前的bean定义信息
			Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
			// 已经解析过的
			Set<String> alreadyParsedClasses = new HashSet<>();
			for (ConfigurationClass configurationClass : alreadyParsed) {
				alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
			}
			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());

	// 注册通知
	if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
		sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
	}
	if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
		((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
	}
}
ConfigurationClassUtils.checkConfigurationClassCandidate

在这里插入图片描述

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
	// 获取全限定类名
	String className = beanDef.getBeanClassName();
	// 猜测是判断是正常流程的bean定义信息,像FactoryBean不进行解析
	if (className == null || beanDef.getFactoryMethodName() != null) {
		return false;
	}
	// 获取到注解信息
	AnnotationMetadata metadata;
	// 如果属于注解标注的bean定义信息
	if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
		metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
	}
	else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
		// 排除掉不能加载bean定义信息
		Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
		if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
				BeanPostProcessor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
				EventListenerFactory.class.isAssignableFrom(beanClass)) {
			return false;
		}
		metadata = AnnotationMetadata.introspect(beanClass);
	}
	else {
		try {
			//强制去获去注解metadata 
			MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
			metadata = metadataReader.getAnnotationMetadata();
		}catch (IOException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Could not find class file for introspecting configuration annotations: " +className, ex);
			}
			// 如果强制拿不到直接返回false
			return false;
		}
	}
	Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
	// 如果是Configuration注解修饰,并且是动态代理的,标识为 full
	if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
	}
	// isConfigurationCandidate 判断是否是@Component、@ComponentScan、@Import、@ImportResource、@Bean注解修饰
	// 如果被@Configuration注解修改了,那么里面是可以配置@Bean,所以最后需要判断下
	// 如果是这些注解修饰的bean定义信息都会被标识为普通的对象 标识为 lite
	else if (config != null || isConfigurationCandidate(metadata)) {
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
	}else {
		return false;
	}

	// 到这里已经确定是注解修饰的bean,并且是被spring认可的正常流程创建的bean
	//获取order值赋给bean定义信息
	Integer order = getOrder(metadata);
	if (order != null) {
		beanDef.setAttribute(ORDER_ATTRIBUTE, order);
	}
	return true;
}
ConfigurationClassParser.processConfigurationClass
protected void processConfigurationClass(ConfigurationClass configClass,Predicate<String> filter) throws IOException {
	// 判断是否跳过解析
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}
	// 如果缓存中存在,进行合并
	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		if (configClass.isImported()) {
			if (existingClass.isImported()) {
				existingClass.mergeImportedBy(configClass);
			}
			return;
		}
		else {
			this.configurationClasses.remove(configClass);
			this.knownSuperclasses.values().removeIf(configClass::equals);
		}
	}
	// 获取到类信息
	SourceClass sourceClass = asSourceClass(configClass, filter);
	do {
		// 开始执行配置类的解析
		sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
	}
	while (sourceClass != null);
	// 添加到缓存
	this.configurationClasses.put(configClass, configClass);
}
ConfigurationClassParser.doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {
	// 如果是@Component注解
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// 需要递归进行解析内部的配置类
		processMemberClasses(configClass, sourceClass, filter);
	}

	// 解析 @PropertySource
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(),PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}else {
			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}

	// 处理@ComponentScan注解
	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) {
			// 扫描路径的对应的注解,并生成bean定义信息
			Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			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注解
	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

	// 处理@ImportResource
	AnnotationAttributes importResource =
			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
	if (importResource != null) {
		String[] resources = importResource.getStringArray("locations");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// 处理 @Bean 
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// 处理接口中的注解,1.8之后支持
	processInterfaces(configClass, sourceClass);

	// 处理父类
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
			this.knownSuperclasses.put(superclass, configClass);
			// 返回父类,然后继续解析父类
			return sourceClass.getSuperClass();
		}
	}
	return null;
}
ConfigurationClassParser.processMemberClasses 解析@Component
@Component
public class CommonConfig {
	@Component
	class InnerClass{
		
		@Component
		class InnerInnerClass{
		
		} 
	} 
}

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate<String> filter) throws IOException {
	// 获取@Component内部配置类
	Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
	if (!memberClasses.isEmpty()) {
		List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
		for (SourceClass memberClass : memberClasses) {
			if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
				//符合条件添加到容器中,用于递归解析
				candidates.add(memberClass);
			}
		}
		// 配置的注解类是可以添加@Order注解的,这里对Order进行排序
		OrderComparator.sort(candidates);
		for (SourceClass candidate : candidates) {
			// 验证,重启解析
			if (this.importStack.contains(configClass)) {
				this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
			}else {
				// 添加递归标示 (压栈)
				this.importStack.push(configClass);
				try {
					// 递归解析
					processConfigurationClass(candidate.asConfigClass(configClass), filter);
				}finally {
					// 添加递归标示 (弹出)
					this.importStack.pop();
				}
			}
		}
	}
}
ConfigurationClassParser.processPropertySource 解析@PropertySource并把配置文件加载到propertySourceList
@Configuration // 这里必须要添加
@PropertySource(value = "application.properties")
public class CommonConfig {
}
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
	// 获取@PropertySource 属性值
	String name = propertySource.getString("name");
	if (!StringUtils.hasLength(name)) {
		name = null;
	}
	String encoding = propertySource.getString("encoding");
	if (!StringUtils.hasLength(encoding)) {
		encoding = null;
	}
	// 获取value值 value=“classpath*:*.properties”
	String[] locations = propertySource.getStringArray("value");
	Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
	boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
	Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
	//得到资源工厂
	PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));

	for (String location : locations) {
		try {
			// 处理占位符
			String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
			Resource resource = this.resourceLoader.getResource(resolvedLocation);
			// 解析配置文件,把解析出的配置文件加载到 propertySourceList
			addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
		}catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
			if (ignoreResourceNotFound) {
				if (logger.isInfoEnabled()) {
					logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
				}
			}else {
				throw ex;
			}
		}
	}
}
ConfigurationClassParser.getImports 获取到@Import所加载的资源
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
	// 存放加载的资源类
	Set<SourceClass> imports = new LinkedHashSet<>();
	// 递归标识
	Set<SourceClass> visited = new LinkedHashSet<>();
	// 处理@Import注解导入的类
	collectImports(sourceClass, imports, visited);
	return imports;
}
ConfigurationClassParser.getImports 递归获取@Import注解标注的类
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)throws IOException {
	if (visited.add(sourceClass)) {
		for (SourceClass annotation : sourceClass.getAnnotations()) {
			String annName = annotation.getMetadata().getClassName();
			if (!annName.equals(Import.class.getName())) {
				// 如果存在多层嵌套关系,那么进行递归获取
				collectImports(annotation, imports, visited);
			}
		}
		// 把@Import 标注的类添加到集合中
		imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
	}
}
ConfigurationClassParser.processImports 解析@
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,boolean checkForCircularImports) {
	
	if (importCandidates.isEmpty()) {
		return;
	}

	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else {
		this.importStack.push(configClass);
		try {
			// 循环前面扫描到的所有@Import标注的类
			for (SourceClass candidate : importCandidates) {
				// 如果属于ImportSelector ,
				if (candidate.isAssignable(ImportSelector.class)) {
					// 创建实例
					Class<?> candidateClass = candidate.loadClass();
					ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,this.environment, this.resourceLoader, this.registry);
					// 获取过滤器
					Predicate<String> selectorFilter = selector.getExclusionFilter();
					if (selectorFilter != null) {
						exclusionFilter = exclusionFilter.or(selectorFilter);
					}
					// 如果需要延期处理的话,添加到容器中
					if (selector instanceof DeferredImportSelector) {
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					}else {
						//不需要延期处理,那么进行递归处理(@Import类下有可能还有@Import)
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
						processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
					}
				}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
					// 处理 ImportBeanDefinitionRegistrar类型
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}else {
					// 当作配置类进行处理 @Configuration
					this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
				}
			}
		}catch (BeanDefinitionStoreException ex) {
			throw ex;
		}catch (Throwable ex) {
			throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configClass.getMetadata().getClassName() + "]", ex);
		}finally {
			this.importStack.pop();
		}
	}
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值