spring boot源码阅读

先看官网。。。。。

https://spring.io/projects/spring-boot

总览

通过Spring Boot,可以轻松地创建独立的,基于生产级别和基于Spring的应用程序,并且可以“运行”它们。

我们对Spring平台和第三方库坚持自己的的观点,因此您可以以最小的麻烦开始使用。大多数Spring Boot应用程序只需要需要非常少的的Spring配置。

特征

  • 创建独立的Spring应用程序

  • 直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件)

  • 提供默认的“入门”依赖项,以简化构建配置

  • 尽可能自动配置Spring和第三方库

  • 提供可用于生产的功能,例如指标,运行状况检查和外部化配置

  • 完全没有代码生成,也不需要XML配置

入门

 


好了,开始看源码吧
 
 
1、先找到入口(项目创建自己搞,这都不会看毛源码):
  主类->SpringApplication.run->this.run->new SpringApplication().run()
2、就从SpringApplication的run(String... args)方法开始看

  2.1、先看注解:运行Spring的应用程序,正在创建和刷新一个新的ApplicationContext(Spring IOC容器),大体的意思就是要创建并刷新一个IOC容器,也就是说Spring boot基于IOC容器的扩展,不同的地方应该大部分在于扩展的部分

   /**
     * Run the Spring application, creating and refreshing a new
     * {@link ApplicationContext}.
     * @param args the application arguments (usually passed from a Java main method)
     * @return a running {@link ApplicationContext}
     */

  2.2、外围的主要方法就是这些了,直接看注释

  /**
     * Run the Spring application, creating and refreshing a new
     * {@link ApplicationContext}.
     * @param args the application arguments (usually passed from a Java main method)
     * @return a running {@link ApplicationContext}
     */
    public ConfigurableApplicationContext run(String... args) {
        // 1、计时器 启动
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        // 2、设置一个可配置的应用上下文(IOC容器)变量,赋默认值
        ConfigurableApplicationContext context = null;
        // 3、初始化一个异常报告器列表
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        // 4、配置一个java.awt.headless系统属性,好像是用来配置像linux服务器这种没有显示设备的机子用的
        configureHeadlessProperty();
        // 5、获取Spring应用程序运行监听器,这些监听器看起来主要应用在spring boot的run方法之中,没有和spring refresh方法里面的一起
        SpringApplicationRunListeners listeners = getRunListeners(args);
        // 6、看上去像是启动监听器,实际上是传播starting事件给监听器,listeners可以理解为组合模式吧,这个容器包裹了一堆监听器,对外的方法基本上都是遍历调用这些监听器的具体方法
        // (一)第一次监听器传播 应用启动事件
        listeners.starting();
        try {
            // 7、将命令行参数包裹到容器中
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 8、初始化一个可配置的环境(根据应用类型),这边主要是准备工作(listeners将在这里第二次调用,(二)第二次监听器传播,环境准备就绪事件)
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            // 9、从环境变量中读取是否忽略beanInfo信息的配置,并设置到系统参数
            configureIgnoreBeanInfo(environment);
            // 10、打印banner,就是用命令行打印出spring boot的那个logo的一些信息
            Banner printedBanner = printBanner(environment);
            // 11、给应用上下文设置一个实际的对象(根据应用类型)
            context = createApplicationContext();
            // 12、从spring.factory中读取并初始化异常报告器
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            // 13、context的准备工作,包括一些属性设置,初始化器的调用,(三)第三次监听器传播,context读取就绪事件...
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 14、刷新容器,基本上就又到了Spring IOC的核心方法,refresh里面了
            refreshContext(context);
            // 15、扩展用的,在刷新context之后调用
            afterRefresh(context, applicationArguments);
            // 1、计时器 结束
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
            }
            // 16、(四)第四次监听器传播,应用启动事件
            listeners.started(context);
            // 17、执行一些注册好的命令对象ApplicationRunner或CommandLineRunner的bean list
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
            // 18、(五)第五次监听器传播,应用运行中事件
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

  2.3、里面各自有很多细节,如果一个一个讲没太大意思,还是要自己看;主要还是看看Spring boot的自动配置、自动装配的部分

    2.3.1、重点外围方法:prepareContext这里面主要是有两个事情,一个是注册了我们的主类到DefaultListableBeanFactory到BeanDefinition里面(后面会用来作为根节点解析配置文件)【入口是load方法】,另一个是init了添加了两个beanFactoryPostProcess【入口是:applyInitializers】

    

   2.3.2、refreshContext这个方法看名字就知道最终会调用到Spring的refresh方法,spring的就不再细看了,直接看spring预留用来执行扩展方法的invokeBeanFactoryPostProcessors方法

    最终跟到PostProcessorRegistrationDelegate这个类中的invokeBeanFactoryPostProcessors方法

  

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

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();
        
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
            // 1、分组
            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<>();

            // 2、执行优先级最高的BeanDefinitionRegistryPostProcessors处理器 开始
            // First, invoke the BeanDefinitionRegistryPostProcessors that implement 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);
            // 我只引入了spring-boot-web,这里仅仅获取到了ConfigurationClassPostProcessor,
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
            // 2、执行优先级最高的BeanDefinitionRegistryPostProcessors处理器  结束

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement 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();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            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();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }
   ConfigurationClassPostProcessor这个对象的postProcessBeanDefinitionRegistry方法会先被执行,里面方法还比较杂
   后面会运行到processConfigBeanDefinitions这个方法里面
  

可以看到最终只过滤到了这个主类

再看到parse这行代码

 

接下来这个方法实在代码有点多,反正上面这个方法入口进去之后,大致就是不断自下而上(就是子配置加载完,再加载父类的配置,

直到没有父类)地解析配置(主要是注解) 

大概看一下也能知道,@CompentScan和@Import,都是自动配置装配相关的,这里会尽可能地将配置都解析出来

(不过应该还不包含一些要动态引入的,其次是这里还不是最终处理的逻辑,主要还是解析) 解析完了之后我们回

到下面这个方法

 

 接下来这个就是最终实际执行的方法

 

注意看下上面这个group实际是AutoConfigurationImportSelector

 上面这个方法,实际最终从spring.factories文件里面读取出来n多个(目前我的项目里面是120多个),自动化配置需要加载的配置文件

不过最终还会过滤掉一些重复或者不需要的配置,这边过滤完之后是剩下20几条 

最后又会回到解析配置的那步(就是自下而上一直解析配置的那里)

反正。。。。最终解析完之后,又到了spring的refresh方法里面去实例化bean,大致是这样吧。

从上面的过程来看,其实也可以推导出,如果我们要自己设置一个starter,那么基本上只要自己配置一个class,并且将其写入spring.factories里面的,基本上就ok了

org.springframework.boot.autoconfigure.EnableAutoConfiguration=

ps:由于理解有限,可能有错误的点自己也不清楚,读者自己要自己留意下,哈哈(也许有坑),毕竟看源码容易把人看晕掉

简单总结下:

  1. SpringApplication的一些方法执行
    1. prepareContext -> 添加主类到要扫描的配置文件列表中,注册BeanFactoryPostProcess
    2. refreshContext -> AbstractApplicationContext refresh()
  2. AbstractApplicationContext的refresh方法
  3. invokeBeanFactoryPostProcessors方法
  4. 调用优先级最高的BeanFactoryPostProcess(ConfigurationClassPostProcessor)处理BeanDefinition的注册
  5. 调用到ConfigurationClassParser解析,
    1. 初步解析(初步解析是通过主类,将所有配置加载寄哪里)
    2. 继续调用importSelector的解析(相当于解析到了@Import,然后将AutoConfigurationImportSelector先放到一个列表中,在这一步继续解析)
    3. 最终应该又得调用初步解析中调用到的方法,把所有的配置都加载出来
  6. AbstractApplicationContext的finishBeanFactoryInitialization方法,把所有配置和普通bean都实例化
  7. 最终程序启动,写的太细的话,绝对要晕,这边就写个大概

反正思路吧。首先我们先读过spring 源码,就大概知道留了个beanFactoryPostProcess的口给扩展的人了

其次,通过使用,我们知道关键的注解是EnableAutoConfiguration(当然一般在这里我们还不一定知道和@Import(AutoConfigurationImportSelector.class) 的关系)

所以只能跟着源码运行最终发现初步解析之后,还会继续处理ImportSelector的解析,我们才发现上面这个关系

最终理解了,就是先加载主类配置,通过主类配置发现EnableAutoConfiguration,再通过EnableAutoConfiguration import AutoConfigurationImportSelector

AutoConfigurationImportSelector解析了spring.factories里面的EnableAutoConfiguration下的配置列表

千万千万不要被那个重复解析的代码给绕晕了,其次是不要在这里找实例化代码,如果我理解没错的话,实例化最终是spring 容器的事情,还有就是不要用spring cloud的版本来看,我差点没被搞死。。。第一次看还是老实点,看纯净版的

原文地址:https://www.cnblogs.com/gabin/p/13754039.html