SpringBoot源码解析

SpringBoot源码解析

1.启动的过程:

SpringBoot源码解析_第1张图片

  • 首先在main函数中启动当前应用程序(SpringApplication启动)
  • 创建SpringApplication对象(new SpringApplication()).在对象的构造方法中进行参数的初始化工作,最主要的是判断当前应用程序的类型以及初始化器和监听器,在此过程中会加载整个应用程序中的spring.factories文件,将文件的内容放在缓存对象中,方便后续获取,具体步骤如下:
    • 配置resourceloader
    • 判断当前应用程序的类型
    • 获取初始化器的实例对象
    • 获取监听器的实例对象
    • 找到当前应用程序的主类,开始执行
  • SpringApplication对象创建完成之后开始执行run()方法,来完成整个启动过程.而run方法中主要的步骤如下:
    • 设置启动时间
    • 设置上下文
    • 设置异常报告器
    • 创建监听器并从中获取符合监听事件的几个监听器
    • 配置命令行参数
    • 准备应用程序运行的环境
    • 接着是核心的上下文部分,分为prepareContext()上下文的前置处理,refreshContext()核心方法,就是spring中的refresh()方法,其中的beanFactoryPostProcessor()完成自动装配的核心,afterRefresh()上下文后置结束处理
    • 之后就是发布应用上下文启动,执行runner()运行器
    • 发布应用上下文就绪并返回
    • SpringApplication启动结束

2.具体的run()方法源码如下:

public ConfigurableApplicationContext run(String... args) {
   		//设置启动时间
        long startTime = System.nanoTime();
    	//设置上下文
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
    	//创建监听器并从中获取符合监听事件的几个监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            //配置命令行参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备应用程序运行的环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //打印banner(也就是那个p用没有的图标)
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            //prepareContext和refreshContext是自动装配的核心方法 而且这个refreshContext方法就是spring中的refresh()方法 使用的就是里面的beanFactoryPostProcessor()来实现的自动装配
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            //发布应用上下文启动,执行runner()运行器
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            listeners.started(context, timeTakenToStartup);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }
    
		//发布应用上下文就绪并返回
        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }

3.自动装配的原理

自动装配的实现就是为了从spring.factories文件中获取到对应的bean对象,并且由spring容器帮我们进行管理.

  • 当启动SpringBoot应用程序的时候会先创建SpringApplication对象,在对象的构造方法中进行参数的初始化工作,最主要的是判断当前应用程序的类型以及初始化器和监听器,在此过程中会加载整个应用程序中的spring.factories文件,将文件的内容放在缓存对象中,方便后续获取
  • SpringBoot对象创建完成之后,开始执行run()方法来完成整个启动过程.启动过程中主要包括的两个方法:prepareContext()和refreshContext()方法,在这两个关键的步骤中完成自动装配的核心功能
  • 在prepareContext()方法中主要完成的是对上下文对象的初始化操作,包括属性值的设置,在整个过程中最重要的方法是load(),主要完成将当前启动类作为一个beanDefinition注册到registry(注册表)中,方便后续进行BeanFactoryPostProcesser调用执行的时候,找到对应的主类,来完成对@SpringBootApplication,@EnableAutoConfiguration等注解的解析工作(注意:要完成这些注解的解析工作,必须要获取到启动类)
  • 在refreshContext()方法中,会调用spring中的refresh()方法(refresh()方法一共有13个非常关键的方法来完成整个spring应用程序的启动),在自动装配中会调用invokeBeanFactoryPostProcessor()方法,在此方法中主要是对ConfigurationClassPathPostProcessor类的处理(它是BeanFactoryPostProcessor的子类,也是BeanDefinitionReaderPostProcessor的子类).在调用的时候会先调用BeanDefinitionReaderPostProcessor中的postProcessorBeanDefinitionRegistry方法,然后调用PostProcessBeanFactory()方法,在执行postProcessorBeanDefinitionRegistry方法的时候会解析处理各种注解,最主要的是对@Import注解的解析
  • 在解析@Impo注解的时候,会有一个getInstance()方法,从主类中递归解析注解,把所有@Import的注解都解析到,然后在processImport()方法中对Import的类进行分类,此处主要识别的是@Import(AutoConfigurationImportSelect.class)中的AutoConfigurationImportSelect,在后续的过程中调用deferredImportSelectorHandler()中的方法来完成EnableAutoConfiguration对象的加载,之后获取到spring.factories找到大量的自动装配的类(并不是所有的类都会用到),将不适用的装配类移除,过滤掉多余的装配类(starter的作用就是确定那些配置类是需要的,哪些是不需要的)
    SpringBoot源码解析_第2张图片

你可能感兴趣的:(LeetCode刷题笔记,spring,boot,java,spring,后端,微服务)