Springboot自动装配的实现流程

带着这个问题到网上搜索,大多数文章在解释这个问题的时候,上来就是@SpringBootApplication注解中找@EnableAutoConfiguration注解,然后找到@Import(AutoConfigurationImportSelector.class)注解,然后就到AutoConfigurationImportSelector类中找,惊呆😮~

不过也没错,最后确实是因为这个注解这个类完成的自动装配,但是Spring是如何从开始的注解一步一步完成自动装配的呢?

接下来一步一步的调试跟踪,众所周知任何一个SpringBoot项目都是从主启动类的main方法开始的,那就从main开始!

@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}

接下来跟踪run方法,一步步来到如下run方法:

public ConfigurableApplicationContext run(String... args) {
   //StopWatch主要用来对应用启动统计耗时用的
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
  //注册事件监听器,以便于在不同的事件发生时候,能在外部注册事件回调
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
      //项目启动时的Spring的logo就是在这里打印的
			Banner printedBanner = printBanner(environment);
      //创建上下文
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
      //准备上下文
      //1、为上下文注入系统环境、应用一些初始化器
      //2、load方法加载主启动类定义信息
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
      //刷新容器,跟进该方法
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			//...
		return context;
	}

跟随refreshContext(context)方法,一路跟踪发现回来到Springframeworkrefresh方法,其实不用看也知道肯定会来到这里,因为整个SpringBoot就是在Spring基础之上开发的,主要就是添加了自动装配,当然,这也是这篇文章的主要目的。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 主要功能设置一些状态flag
			prepareRefresh();
			// 这里是获取上面run方法中已经创建了的beanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// 准备bean工厂,主要工作就是注入Spring必须的一些组件
			prepareBeanFactory(beanFactory);
			try {
				// 这个方法在Spring层面是空实现,是留作子类定制实现
				postProcessBeanFactory(beanFactory);
				// 重点来了,在这里执行预先注入的BeanFactoryPostProcessors
				invokeBeanFactoryPostProcessors(beanFactory);
        
        ......
          
      }
	}

跟着invokeBeanFactoryPostProcessors进入

//实例化已经注册的BeanFactoryPostProcessor bean,并执行
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   //进入该方法
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),这个方法特别长,总得来说,这个方法的主要工作就是将已经注册到beanFactory的各种FactoryBeanPostProcessor分门别类,按照优先级有序执行。

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// 先执行BeanDefinitionRegistryPostProcessors类型的增强器.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// 首先执行实现了PriorityOrdered接口的增强器.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
      //currentRegistryProcessors内部包括一个ConfigurationClassPostProcessor,跟踪改方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 接下来执行实现了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);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 最后执行剩余的增强器.
			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();
			}

			// 执行增强器的回调方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		......
	}

跟踪上面的invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)方法,分别调用ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法->ConfigurationClassPostProcessor.processConfigBeanDefinitions()方法,并且将会在``ConfigurationClassPostProcessor.processConfigBeanDefinitions`内部解析程序主启动类

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
  	//获取到容器中已经注入的bean信息
		String[] candidateNames = registry.getBeanDefinitionNames();
		//遍历容器注入的bean信息,找出所有的配置类,执行结果中会包括程序启动类()
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// 如果已注入的bean信息中没有一个 @Configuration 注解标记的类,这肯定是不合理的
		if (configCandidates.isEmpty()) {
			return;
		}

		// 将得到的所有配置类排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});


		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 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 {
      //在这里真正执行解析配置类操作,解析程序主启动类, 进入该方法
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			......
    }
	}

进入parser.parse方法:

//方法的入参是包含主启动类的BeanDefinitionHolder的一个set
public void parse(Set<BeanDefinitionHolder> configCandidates) {
		this.deferredImportSelectors = new LinkedList<>();

		for (BeanDefinitionHolder holder : configCandidates) {
      //遍历set得到主启动类定义信息,主启动类的BeanDefinition的类型是AnnotatedBeanDefinition,所以会进入try块中的第一个if分支
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
          //进入该if分支
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		processDeferredImportSelectors();
	}

上面parse方法调用链:ConfigurationClassParser.parse -> ConfigurationClassParser.processConfigurationClass -> ConfigurationClassParser.doProcessConfigurationClass,来到ConfigurationClassParser.doProcessConfigurationClass方法:

//转了一大圈,发现这个方法前缀do...才是真正干活的
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		// 递归处理内部类,这个方法调用一圈后又会回到当前方法,递归嘛...
		processMemberClasses(configClass, sourceClass);

		// 处理 @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.warn("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() &&
				......
		}

		// 处理 @Import 注解
    // getImports(sourceClass),会递归地扫描类注解的继承树上所有的Import注解信息,那么其必然至少包括
    // @Import(AutoConfigurationImportSelector.class) 和 @Import(AutoConfigurationPackages.Registrar.class)
		processImports(configClass, sourceClass, getImports(sourceClass), true);
		......
		return null;
	}

处理 @Import 注解完成后,当前方法返回,逆着调用链一路返回到ConfigurationClassParser.parse方法,并继续执行processDeferredImportSelectors()方法,此时已经将主启动类上的@Import(AutoConfigurationImportSelector.class)得到:

private void processDeferredImportSelectors() {
        //如果成员变量中的导入选择器为null,则说明不需要进行处理
        //成员中的导入选择器其实是在处理@import标签时,判断如果是importSelector类型,则会放置到成员变量中。
        //@SpringBootApplication->@EnableAutoConfiguration->@Import(AutoConfigurationImportSelector.class)
        //所以实际上,这里的导入选择器只会是AutoConfigurationImportSelector
        List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
        this.deferredImportSelectors = null;
        if (deferredImports == null) {
            return;
        }
        //先进行排序
        deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
        //这里其实就是组->组对应的导入选择器,grouping封装了group以及List<ImportSelector>
        Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();
        Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
        //根据importSelector中的group进行分组
        for (DeferredImportSelectorHolder deferredImport : deferredImports) {
            //获取该导入选择器的组
            Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
            //若该分组不存在则进行创建
            DeferredImportSelectorGrouping grouping = groupings.computeIfAbsent(
                    (group != null ? group : deferredImport),
                    key -> new DeferredImportSelectorGrouping(createGroup(group)));
            //将该导入选择器加入到对应的分组中
            grouping.add(deferredImport);
            configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
                    deferredImport.getConfigurationClass());
        }
        //遍历执行每个分组,由于这里只有AutoConfiurationImportSelector所以我们只关注这个类即可。
        for (DeferredImportSelectorGrouping grouping : groupings.values()) {
            //获取需要自动装配的所有类,逐个去处理,那么如何获取则是关键。
          // -1-
            grouping.getImports().forEach(entry -> {
                ConfigurationClass configurationClass = configurationClasses.get(entry.getMetadata());
                try {
                    //处理自动装配的类,这里其实就是对自动装配的配置类进行处理,与处理@import的方法是一致的,感兴趣可以往里面看看。
                    processImports(configurationClass, asSourceClass(configurationClass),
                            asSourceClasses(entry.getImportClassName()), false);
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to process import candidates for configuration class [" +
                            configurationClass.getMetadata().getClassName() + "]", ex);
                }
            });
        }
    }
}

1处调用链grouping.getImports()->AutoConfigurationImportSelector.process->AutoConfigurationImportSelector.selectImports,这里就是selectImports是关键:

public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
   //就是这个方法,获取所有的候选配置类
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return StringUtils.toStringArray(configurations);
	}

进入方法getCandidateConfigurations:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
  	//根据类别加载配置类信息
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

其中的SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()),是根据指定类别到spring.factories文件加载类,而getSpringFactoriesLoaderFactoryClass()实现如下:

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}

在这里得到EnableAutoConfiguration,也就是说从spring.factories文件中加载EnableAutoConfiguration类别下的类:

在这里插入图片描述

这么写配置类都将被加入,然后经过排除、去重、根据配置类条件决定是否加载等操作后,剩余的类被包括,然后返回到ConfigurationClassPostProcessor.processConfigBeanDefinitions方法中,通过loadBeanDefinitions(configClasses)将定义信息导入。

至此,所有的满足条件的自动配置类信息都被纳入容器,然后随着容器初始化bean的生命周期,这些自动配置bean也被初始化,至此完成自动装配。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值