SpringBoot 核心原理分析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析DNS,个人版 1个月
云解析 DNS,旗舰版 1个月
简介: SpringBoot 核心原理分析

spring-boot-loader



image.png


  1. maven将SpringBoot启动类打到fatJar


  1. JarLauncher


  1. SpringApplication


SpringBoot项目的入口



启动类:


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


SpringApplication的run方法


//AbstractApplicationContext#refresh
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
          args);
      // 准备配置环境,读取配置文件到environment,你写的一大堆配置都在这读取
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
          applicationArguments);
      Banner printedBanner = printBanner(environment);
      //创建应用上下文
      context = createApplicationContext();
      analyzers = new FailureAnalyzers(context);
      //准备上下文环境,注册bean定义到context,这里的自定义Bean目前只有:
      //BootApplication,我们自定义的启动类
      prepareContext(context, environment, listeners, applicationArguments,
          printedBanner);
      //刷新上下文,这块是关键逻辑
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
        new StartupInfoLogger(this.mainApplicationClass)
            .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
    }
    catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
    }
}
//AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
        // Tell the subclass to refresh the internal bean factory.
        // 此处的beanFactory是DefaultListenableBeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // Prepare the bean factory for use in this context.
        //为bean工厂添加ClassLoader和一些内置的BeanPostProcessor
        prepareBeanFactory(beanFactory);
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
            // Invoke factory processors registered as beans in the context.
            //触发内部自动配置的BeanFactoryPostProcessor,SpringBoot自动配置就是在这扩展实现的
            invokeBeanFactoryPostProcessors(beanFactory);
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            // Initialize message source for this context.
            initMessageSource();
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
            // Initialize other special beans in specific context subclasses.
            onRefresh();
            // Check for listener beans and register them.
            registerListeners();
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
            // Last step: publish corresponding event.
            finishRefresh();
        }
        catch (BeansException ex) {
            //...
        }finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //主要逻辑在这里实现
  PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
  //...
    }
  }


PostProcessorRegistrationDelegate


//ConfigurationClassPostProcessor类来解析@Configuration注解
public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<String>();
    if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
          BeanDefinitionRegistryPostProcessor registryProcessor =
              (BeanDefinitionRegistryPostProcessor) postProcessor;
          registryProcessor.postProcessBeanDefinitionRegistry(registry);
          registryProcessors.add(registryProcessor);
        }
        else {
          regularPostProcessors.add(postProcessor);
        }
      }
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the bean factory post-processors apply to them!
      // Separate between BeanDefinitionRegistryPostProcessors that implement
      // PriorityOrdered, Ordered, and the rest.
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
      // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
      //此处获取Spring内置的ConfigurationClassPostProcessor,用来处理@Configuration注解
      String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          //此处实例化ConfigurationClassPostProcessor
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
        }
      }
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      //处理@Configuration注解
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();
       //以下代码省略...
    }
    //以下代码省略...
  }


@SpringBootApplication:


主要由:@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三个注解组成,本质是就是一个@Configuration类


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication{
    //以下代码省略...
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    //以下代码省略...
}


ConfigurationClassPostProcessor解析配置@Configuration:


public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
    String[] candidateNames = registry.getBeanDefinitionNames();
    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));
      }
    }
    // Return immediately if no @Configuration classes were found
    if (configCandidates.isEmpty()) {
      return;
    }
    // Sort by previously determined @Order value, if applicable
    Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
      @Override
      public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
      }
    });
    // 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 && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
        BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
        this.componentScanBeanNameGenerator = generator;
        this.importBeanNameGenerator = generator;
      }
    }
    // Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    do {
      //解析我们配置SpringBoot启动类:BootApplication
      parser.parse(candidates);
      parser.validate();
      //...
    }
    while (!candidates.isEmpty());
    //...
  }


ConfigurationClassParser具体的解析操作:


public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
    for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
        if (bd instanceof AnnotatedBeanDefinition) {
          //1、执行具体的解析工作
          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) {
        //...
      }
    }
    //2、处理DeferredImportSelector,此处是:EnableAutoConfigurationImportSelector
    processDeferredImportSelectors();
}
//ConfigurationClassParser中的具体的解析逻辑
 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
    // Recursively process any member (nested) classes first
    processMemberClasses(configClass, sourceClass);
    // Process any @PropertySource annotations
    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");
      }
    }
    // Process any @ComponentScan annotations
    //处理@ComponentScan注解,默认是BootApplication所在的包
    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) {
        // The config class is annotated with @ComponentScan -> perform the scan immediately
        //解析@ComponentScan扫描的包下面的组件,如:@Component,@Service等
        Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
        // Check the set of scanned definitions for any further config classes and parse recursively if needed
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
          BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
          if (bdCand == null) {
            bdCand = holder.getBeanDefinition();
          }
          if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            //此处递归解析组件中存在的@Configuration注解
            parse(bdCand.getBeanClassName(), holder.getBeanName());
          }
        }
      }
    }
    // Process any @Import annotations
    //处理@Import注解,此处是关键逻辑所在,主要完成两个事情:
    //1、递归解析@Import注解;2、处理@Import注解中配置的类,此处主要是将EnableAutoConfigurationImportSelector.class类找出来放在缓存中,让上面的 processDeferredImportSelectors();方法处理
    processImports(configClass, sourceClass, getImports(sourceClass), true);
    //...
}
//2、处理DeferredImportSelector,此处是:EnableAutoConfigurationImportSelector
private void processDeferredImportSelectors() {
    List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
    this.deferredImportSelectors = null;
    Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
    for (DeferredImportSelectorHolder deferredImport : deferredImports) {
      ConfigurationClass configClass = deferredImport.getConfigurationClass();
      try {
        //获取自动配置的类信息,具体由EnableAutoConfigurationImportSelector导入
        String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
        processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
      }
      catch (BeanDefinitionStoreException ex) {
        throw ex;
      }
      catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
            "Failed to process import candidates for configuration class [" +
            configClass.getMetadata().getClassName() + "]", ex);
      }
    }
  }


EnableAutoConfigurationImportSelector的selectImports方法:


public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            try {
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                //具体由SpringFactoriesLoader实现自动配置类的导入工作
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                configurations = this.removeDuplicates(configurations);
                configurations = this.sort(configurations, autoConfigurationMetadata);
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportListeners(configurations, exclusions);
                return (String[])configurations.toArray(new String[configurations.size()]);
            } catch (IOException var6) {
                throw new IllegalStateException(var6);
            }
        }
    }


SpringFactoriesLoader导入自动配置类:


public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    try {
        //从各个自动配置的Starter的META-INF/spring.factories配置文件中导入自动配置类
        Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
        ArrayList result = new ArrayList();
        while(urls.hasMoreElements()) {
            URL url = (URL)urls.nextElement();
            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
            String factoryClassNames = properties.getProperty(factoryClassName);
            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
        }
        return result;
    }
    catch (IOException ex) {
      //...
    }
  }


SpringBoot的核心技术原理:


自动配置及Bean的自动发现,可以看到SpringBoot最终是使用SpringFactoriesLoader从各个Starter的META-INF/spring.factories配置文件中导入自动配置类信息的。SpringBoot将自动配置类信息导入后会加载到容器中,我们就可以在运行时获取这些配置类来使用了。


目录
相关文章
|
1月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
87 0
|
22天前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
59 11
|
22天前
|
SQL Java 数据库连接
springboot~mybatis-pagehelper原理与使用
【7月更文挑战第15天】MyBatis-PageHelper是用于MyBatis的分页插件,基于MyBatis的拦截器机制实现。它通过在SQL执行前动态修改SQL语句添加LIMIT子句以支持分页。使用时需在`pom.xml`添加依赖并配置方言等参数。示例代码: PageHelper.startPage(2, 10); List&lt;User&gt; users = userMapper.getAllUsers(); PageInfo&lt;User&gt; pageInfo = new PageInfo&lt;&gt;(users); 这使得分页查询变得简单且能获取总记录数等信息。
|
1月前
|
Java 开发者 Spring
深入理解Spring Boot中的自动配置原理
深入理解Spring Boot中的自动配置原理
|
1月前
|
开发框架 Java 开发者
Spring Boot中的自动装配原理
Spring Boot中的自动装配原理
|
2月前
|
消息中间件 Java Maven
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
|
2月前
|
Java 应用服务中间件 Spring
解析Spring Boot自动装配的原理与机制
解析Spring Boot自动装配的原理与机制
43 4
|
1月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue的高质量升学分析系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的高质量升学分析系统的详细设计和实现(源码+lw+部署文档+讲解等)
22 0
|
1月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的数据分析岗位招聘信息与分析附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的数据分析岗位招聘信息与分析附带文章源码部署视频讲解等
12 0
|
1月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的高校成绩分析附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的高校成绩分析附带文章源码部署视频讲解等
25 0