一、简易流程描述

启动类->@SpringBootApplication->@EnableAutoConfiguration-> @Import(AutoConfigurationImportSelector.class)->getCandidateConfigurations

  1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
  2. // 从 Spring.factories 中 获取 EnableAutoConfiguration 下的所有类
  3. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
  4. getBeanClassLoader());
  5. Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
  6. + "are using a custom packaging, make sure that file is correct.");
  7. return configurations;
  8. }

�getSpringFactoriesLoaderFactoryClass

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

从 Spring.factories 中 获取 EnableAutoConfiguration 下的所有类,并进行bean的加载
image.png

二、详细描述

1、SpringApplication

image.png
primarySources 是当前传入的主类信息
mainApplicationClass 是 主类的 Class信息

2、run方法

  1. private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
  2. SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
  3. context.setEnvironment(environment);
  4. // 添加一些 post processing 到 context 中
  5. postProcessApplicationContext(context);
  6. // 在所有的初始化器中添加 context(initializer.initialize(context);)
  7. applyInitializers(context);
  8. // 在所有的监听器中添加 context到对应的事件中 (listener.contextPrepared(context);)
  9. listeners.contextPrepared(context);
  10. if (this.logStartupInfo) {
  11. logStartupInfo(context.getParent() == null);
  12. logStartupProfileInfo(context);
  13. }
  14. // Add boot specific singleton beans
  15. // 获取spring的bean工厂,这里默认是DefaultListableBeanFactory
  16. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  17. beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  18. // beanFactory 的一些信息的设置
  19. if (printedBanner != null) {
  20. beanFactory.registerSingleton("springBootBanner", printedBanner);
  21. }
  22. if (beanFactory instanceof DefaultListableBeanFactory) {
  23. ((DefaultListableBeanFactory) beanFactory)
  24. .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  25. }
  26. if (this.lazyInitialization) {
  27. context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  28. }
  29. // Load the sources
  30. Set<Object> sources = getAllSources();
  31. Assert.notEmpty(sources, "Sources must not be empty");
  32. // 如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中
  33. load(context, sources.toArray(new Object[0]));
  34. // 监听器,发布事件 (listeners.contextLoaded(context))
  35. listeners.contextLoaded(context);
  36. }

直接跳到 prepareContext —> getAllSources
这里获取到主类

  1. public Set<Object> getAllSources() {
  2. Set<Object> allSources = new LinkedHashSet<>();
  3. // 将主类加到 set 中并返回
  4. if (!CollectionUtils.isEmpty(this.primarySources)) {
  5. allSources.addAll(this.primarySources);
  6. }
  7. if (!CollectionUtils.isEmpty(this.sources)) {
  8. allSources.addAll(this.sources);
  9. }
  10. return Collections.unmodifiableSet(allSources);
  11. }

如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中,此时主类就会被注册到AnnotatedBeanDefinitionReader中去,内部会注册到 Beanfactory 中去。

  1. private final AnnotatedBeanDefinitionReader annotatedReader;
  2. // Load beans into the application context.
  3. // source 就是主类
  4. private int load(Class<?> source) {
  5. if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
  6. // Any GroovyLoaders added in beans{} DSL can contribute beans here
  7. GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
  8. load(loader);
  9. }
  10. if (isComponent(source)) {
  11. // 如果包含了 @Component 注解,则将启动类注册到 AnnotatedBeanDefinitionReader 中
  12. this.annotatedReader.register(source);
  13. return 1;
  14. }
  15. return 0;
  16. }

主要实现点

接着直接到refresh�Context中调用spring的refresh的invokeBeanFactoryPostProcessors方法中,(这个方法只有springboot才有实现,spring的这个方法没有实现)
这里回顾 https://www.yuque.com/wangchao-volk4/fdw9ek/ppw8cy#ObsXa

  1. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  2. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
  3. // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
  4. // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
  5. if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
  6. beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
  7. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  8. }
  9. }

getBeanFactoryPostProcessors
image.png
接着 执行 invokeBeanFactoryPostProcessors—》invokeBeanDefinitionRegistryPostProcessors—》_postProcessor.postProcessBeanDefinitionRegistry(registry)—》processConfigBeanDefinitions(在方法 ConfigurationClassPostProcessor 中)
在 parser.parse
(candidates)_; 方法中解析主类
接着在parse中 执行doProcessConfigurationClass
doProcessConfigurationClass 内部使用了方法 processImports
image.png
image.png
接着获取到主类中@Import中的 AutoConfigurationImportSelector.class 和AutoConfigurationPackages.Registrar.class。
doProcessConfigurationClass 执行完后回到 parser.parse(org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set))

  1. public void parse(Set<BeanDefinitionHolder> configCandidates) {
  2. for (BeanDefinitionHolder holder : configCandidates) {
  3. BeanDefinition bd = holder.getBeanDefinition();
  4. try {
  5. if (bd instanceof AnnotatedBeanDefinition) {
  6. parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
  7. }
  8. else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
  9. parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
  10. }
  11. else {
  12. parse(bd.getBeanClassName(), holder.getBeanName());
  13. }
  14. }
  15. catch (BeanDefinitionStoreException ex) {
  16. throw ex;
  17. }
  18. catch (Throwable ex) {
  19. throw new BeanDefinitionStoreException(
  20. "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
  21. }
  22. }
  23. this.deferredImportSelectorHandler.process();
  24. }

使用this.deferredImportSelectorHandler.process(); 处理刚才导入的@Import中的类。
process—》handler.processGroupImports()—》grouping.getImports()
image.png
�group.process(org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process)
image.png
终于找到了getCandidateConfigurations方法。
从 Spring.factories 中 获取 EnableAutoConfiguration 下的所有类。
image.png