spring源码分析-ConfigurationClassPostProcessor

spring-系列



前言

ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcessor接口的实现类。spring通过@Configuration注解加载Bean的具体实现,该类将全面解剖@Configuration注解的神秘面纱。在阅读本文之前读者需要知道什么是BeanDefinitionRegistryPostProcessor,如果还有疑问请移步

ConfigurationClassPostProcessor

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
		PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
   

}

该类是BeanDefinitionRegistryPostProcessor接口扩展的一个经典案例,实现了PriorityOrdered来优先加载@Configuration的Bean,核心入口是BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法,下面详细讨论。

postProcessBeanDefinitionRegistry

	/**
	 * 加载外部定义的Bean,该方法是Configuration,Bean,Component,Service,Import等注解加载Bean的入口
	 * @param registry the bean definition registry used by the application context
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   
		/**
		 * 获取registry注册器hashcode的值
		 */
		int registryId = System.identityHashCode(registry);
		/**
		 * 验证该注册器是否已注册该Bean,表示一个注册器只能注册一次ConfigurationClassPostProcessor
		 */
		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);

		/**
		 * 执行外部Bean的注册逻辑
		 */
		processConfigBeanDefinitions(registry);
	}

processConfigBeanDefinitions(registry)是真正处理Bean的方法。

processConfigBeanDefinitions

	/**
	 * 处理Configuration的Bean加载逻辑
	 * @param registry
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   
		/**
		 * 存储所有被Configuration注解修饰的类
		 */
		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);
				}
			}

			/**
			 * 检查当前是否是一个标准的Bean(检查当前类是否被 Configuration, Component,ComponentSpan,Import,ImportResource 注解修饰)
			 */
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
   
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		/**
		 * 如果未找到@Configuration类,则立即返回
		 */
		if (configCandidates.isEmpty()) {
   
			return;
		}

		// Sort by previously determined @Order value, if applicable、
		/**
		 * 对所有Configuration修饰的类进行排序
		 */
		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
		/**
		 * 检测上下文提供的任何自定义bean名称生成策略,
		 */
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
   
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
   
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
   
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		/**
		 * 给environment赋初始值
		 */
		if (this.environment == null) {
   
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class
		/**
		 * 创建 @Configuration注解的解析类
		 */
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
   
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
			/**
			 * 解析被@Configuration修饰的Bean
			 */
			parser.parse(candidates);

			/**
			 * 验证被@Configuration 注解修饰的类不能被Final修饰
			 * 验证被@Bean 注解修饰的方法可以被重写
			 */
			parser.validate();

			/**
			 * 获取所有的配置类
			 */
			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,这是真正加载Bean的入口
			 */
			this.reader.loadBeanDefinitions(configClasses);
			/**
			 * 加载的类标记为已加载
			 */
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
   
				String[] newCandidateNames = registry.getBeanDefinitionNames
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗德阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值