3、spring核心源码解析之@Configuration注解详解

前情

​ 哎,感觉挤出来的时间仍旧不够用,前天的文章写到深夜一点了,很想定期(原计划每天,感觉不太现实)发一篇高质量的源码解析的博文。

​ 个人的源码解析思路是想从spring核心源码解析作为起点,后续陆续分析mybatis、spring boot 、dubbo源码,这些也都是本人接触并深入过的框架(至于spring cloud全家桶,项目中用过,但并没有深入),感觉还挺有挑战的,希望自己能坚持下去。

​ 本文主要是以@Configuration注解标注的bean是如何实例化的,它和@Component注解又有什么区别?以及简单的扩展,@Configuration注解是spring 以及spring boot 注解驱动中非常核心重要的,掌握它是非常有必要的。

1. @Configuration配置类的实例化的流程分析

​ spring内置的很多注解,如@Autowired、@Import、@Configuration、包括aop动态代理等等,都是通过内置的后置处理器进行处理的。

​ 这次讲的@Configuration注解的核心处理类也是一个后置处理器ConfigurationClassPostProcessor,后文将重点讲解。

​ 在第一篇spring核心之概况流程 的文章里的刷新上下文refresh方法中的 —>调用 beanFactoryPostProcessors beanFactory的后置处理器中就开始如下UML图的中的调用链,有兴趣的小伙伴可以跟踪一下源码,下面来一起看看几个很关键的方法源码。(本人跟踪源码所画)

在这里插入图片描述

在这里插入图片描述

2. ConfigurationClassPostProcessor后置处理器

​ 这个方法是对应在上图中的第三步骤,核心的第一个后置处理在processConfigBeanDefinitions(registry);方法中,这个方法很长,请耐心看下去,该方法中我标记了三个重点,并从这三点进行分别讲解。

	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);
		//处理配置类的bean定义
		processConfigBeanDefinitions(registry);
	}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		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);
				}
			}
			//full模式的配置类,会在postProcessBeanFactory方法中做CGLIB动态代理来增强类
			//重点1 :检查beanDef是不是一个加了@Configuration(full) 或者(lite)加了Component、ComponentScan、Import、ImportResource注解,如果是有配置类,则加入到configCandidates数组中
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
   
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
   
			return;
		}

		// Sort by previously determined @Order value, if applicable
		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;
		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;
				}
			}
		}

		if (this.environment == null) {
   
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class
		//配置类的解析器
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值