SpringBoot——SpringBoot服务启动过程源码详解剖析!

news2024/11/16 19:40:26

文章目录

  • 引言
  • 主要流程
  • 启动类剖析
    • 启动类示例
    • SpringApplication.run()方法
  • 创建SpringApplication对象过程
    • 创建对象源码流程整体分析
      • 不服就debug
    • 创建对象核心过程分解
      • 流程1:deduceFromClasspath()获取主程序类和应用类型
      • 流程2: setInitializers()设置初始化器
      • 流程3: setListeners()设置监听器
      • 流程4:deduceMainApplicationClass()获取主程序类Class
    • getSpringFactoriesInstances()方法分析
      • spring.factories文件
      • getSpringFactoriesInstances()核心源码
    • 创建对象主流程总结
  • 执行SpringApplication.run()方法过程
    • 执行run()方法源码过程整体分析
      • 不服就debug
    • run()方法核心过程分解
      • 流程1:获取并启动运行过程监听器
      • 流程2:准备并构建环境
      • 流程3:IoC容器创建,即创建应用程序上下文
      • 流程4:IoC容器的前置处理
      • 流程5: IoC容器的刷新,即刷新应用程序上下文
      • 流程6: IoC容器的后置处理
      • 流程7: 监听器启动完成
      • 流程8:执行Runners
      • 执行run()方法主流程总结

引言

  用了这么久Spring Boot框架,这次决定对Spring Boot的启动过程一探究竟!卷一波源码!

主要流程

话不多说,直接上主流程总结!
一、创建SpringApplication对象

  1. 获取主程序类和应用类型
  2. 设置初始化器Initializers
  3. 设置监听器Listeners
  4. 获取主程序类Class
    二、执行run()方法
  5. 初始化环境配置
  6. 创建容器,即创建上下文
  7. 容器前置处理
  8. 刷新容器,即刷新上下文(springboot启动核心)
  9. 容器后置处理
  10. 通知监听者,执行Runners,程序启动完成

在这里插入图片描述

启动类剖析

启动类示例

首先,我们先要有一个正确的打开姿势:启动类入口

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

启动类在运行静态run()方法时,是先创建一个SpringApplication对象,再运行对象的run方法,工厂初始配置在构造函数中完成,而run方法定义程序启动总流程。

SpringApplication.run()方法

从启动类中的main()静态方法中点入SpringApplication.run()源码中,可以看到

    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }
    
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    //1. new SpringApplication
    //2. 执行run()方法
        return (new SpringApplication(primarySources)).run(args);
    }

主要涉及到创建SpringApplication对象以及执行run()方法两个过程。

创建SpringApplication对象过程

创建对象源码流程整体分析

    public SpringApplication(Class<?>... primarySources) {
        this((ResourceLoader)null, primarySources);
    }
    //构造对象
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        //打印springboot启动时的图标
        this.bannerMode = Mode.CONSOLE;
        //true的话,打印jvm的启动和运行信息,如启动类、java版本、pid等
        this.logStartupInfo = true;
        //允许通过命令行参数向application.properties中添加属性配置,如--spring.profiles.active=dev
        this.addCommandLineProperties = true;
        //加载默认的类型转换和格式化类 (ApplicationConversionService)
        this.addConversionService = true;
        //开启java的headless模式,此模式允许java服务器可能缺少显示设备、键盘、鼠标等外设的情况下可以使用这种模式
        this.headless = true;
        //注册一个Shutdown Hook,创建线程,该线程用来在java程序关闭后释放资源
        this.registerShutdownHook = true;
        //默认空,读取“dev”、“test”等不同环境的配置
        this.additionalProfiles = Collections.emptySet();
        //会实例化一个环境转换器
        this.isCustomEnvironment = false;
        //是否懒初始化
        this.lazyInitialization = false;
        //默认的ApplicationContextFactory实现,它将为WebApplicationType创建一个适当的上下文。
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        //默认的ApplicationStartup实现,设置DefaultApplicationStartup
        this.applicationStartup = ApplicationStartup.DEFAULT;
        //设置resourceLoader,获取资源,默认null
        this.resourceLoader = resourceLoader;
        //primarySources主启动类判空
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //将主启动类设置到LinkedHashSet集合中存储起来
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        //设置web应用类型为:NONE/SERVLET/REACTIVE
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //从 META-INF/spring.factories 文件中得到 key 为 org.springframework.boot.BootstrapRegistryInitializer 的全类名集合,进行实例化,然后注入 bootstrapRegistryInitializers 属性
        this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        //配置应用程序启动前的初始化对象,从 META-INF/spring.factories 文件中得到初始化器集合,并注入
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //配置应用程序启动前的监听器,从 META-INF/spring.factories 文件中得到监听器实例的集合,并注入
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //获取当前运行的 main 方法所在的类,即主类
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

不服就debug

在这里插入图片描述

创建对象核心过程分解

流程1:deduceFromClasspath()获取主程序类和应用类型

    static WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
            return REACTIVE;
        } else {
            String[] var0 = SERVLET_INDICATOR_CLASSES;
            int var1 = var0.length;

            for(int var2 = 0; var2 < var1; ++var2) {
                String className = var0[var2];
                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                    return NONE;
                }
            }

            return SERVLET;
        }
    }

其中,WebApplicationType枚举类

public enum WebApplicationType {
    NONE,
    SERVLET,
    REACTIVE;
    ... ...
  1. NONE:啥也没有,即程序不额外的启动web容器。
  2. SERVLET:基于servlet的web程序,需启动内嵌的servlet web容器,如Tomcat。
  3. REACTIVE:基于reactive的web程序,需启动内嵌reactive web容器,如webflux。

流程2: setInitializers()设置初始化器

this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

主要设置初始化器ApplicationContextInitializer

    public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
        this.initializers = new ArrayList(initializers);
    }

流程3: setListeners()设置监听器

this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

主要设置监听器ApplicationListener

    public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
        this.listeners = new ArrayList(listeners);
    }

流程4:deduceMainApplicationClass()获取主程序类Class

在这里插入图片描述

    private Class<?> deduceMainApplicationClass() {
        try {
            StackTraceElement[] stackTrace = (new RuntimeException()).getStackTrace();
            StackTraceElement[] var2 = stackTrace;
            int var3 = stackTrace.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                StackTraceElement stackTraceElement = var2[var4];
                //找到主类的main方法
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        } catch (ClassNotFoundException var6) {
        }

        return null;
    }

getSpringFactoriesInstances()方法分析

spring.factories文件

在这里插入图片描述

getSpringFactoriesInstances()核心源码

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    	//获取spring 工厂实例
        return this.getSpringFactoriesInstances(type, new Class[0]);
    }
    
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
        // 获取初始化类的类名
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        // 在通过类名实例化对象
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
    
    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        String factoryTypeName = factoryType.getName();
        //加载spring工厂,读取运行环境中所有META-INF/spring.factories配置
        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
    }
    
    private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            HashMap result = new HashMap();

            try {
                //从META-INF/spring.factories中加载资源
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        String[] var10 = factoryImplementationNames;
                        int var11 = factoryImplementationNames.length;

                        for(int var12 = 0; var12 < var11; ++var12) {
                            String factoryImplementationName = var10[var12];
                            ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                return new ArrayList();
                            })).add(factoryImplementationName.trim());
                        }
                    }
                }

                result.replaceAll((factoryType, implementations) -> {
                    return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                });
                cache.put(classLoader, result);
                return result;
            } catch (IOException var14) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
            }
        }
    }

创建对象主流程总结

  1. 获取主程序类和应用类型
  2. 设置初始化器Initializers
  3. 设置监听器Listeners
  4. 获取主程序类Class
    在这里插入图片描述

执行SpringApplication.run()方法过程

执行run()方法源码过程整体分析

	//run方法 开始启动程序
    public ConfigurableApplicationContext run(String... args) {
    	//记录开始时间戳
        long startTime = System.nanoTime();
        //添加默认的Bootstrap上下文DefaultBootstrapContext实例
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        //配置headless属性
        this.configureHeadlessProperty();
        //获取RunListeners监听器集合,得到EventPublishingRunListener监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //循环启动监听器,通知监听者启动开始
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
        	//封装参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //创建并配置环境,读取配置文件,如application.properties、application.yml
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            //配置忽略bean信息
            this.configureIgnoreBeanInfo(environment);
            //打印 Banner
            Banner printedBanner = this.printBanner(environment);
            //创建IoC容器,即实例化上下文对象
            context = this.createApplicationContext();
            //设置上下文启动
            context.setApplicationStartup(this.applicationStartup);
            //前置处理IoC容器,即准备上下文
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //刷新IoC容器刷新,即刷新上下文
            this.refreshContext(context);
            //后置处理IoC容器
            this.afterRefresh(context, applicationArguments);
            //计算启动时长
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }
			//监听器执行 started 方法,表示启动成功
            listeners.started(context, timeTakenToStartup);
            //执行Runners:CommandLineRunner和ApplicationRunner
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            //监听器执行 ready 方法
            listeners.ready(context, timeTakenToReady);
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }

不服就debug

在这里插入图片描述

run()方法核心过程分解

流程1:获取并启动运行过程监听器

SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
  1. 获取监听器
    private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
		//调用getSpringFactoriesInstances()方法
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
    }
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
        //调用loadFactoryNames从spring.factories文件中获取类全名
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        //创建实例
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
  1. 启动监听器
    void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
    	//启动监听器,通知所有的监听器
        this.doWithListeners("spring.boot.application.starting", (listener) -> {
            listener.starting(bootstrapContext);
        }, (step) -> {
            if (mainApplicationClass != null) {
                step.tag("mainApplicationClass", mainApplicationClass.getName());
            }

        });
    }

    private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) {
    	//创建新步骤并标记其开始
        StartupStep step = this.applicationStartup.start(stepName);
        //通知所有的事件监听者
        this.listeners.forEach(listenerAction);
        //标识
        if (stepAction != null) {
            stepAction.accept(step);
        }
		//标记该步骤结束,且不能修改该步骤的状态
        step.end();
    }

流程2:准备并构建环境

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);

构建环境流程prepareEnvironment()方法详解

            
    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    	//获取并创建对应的环境:SERVLET/REACTIVE或默认
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        //加载系统属性配置
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        //加载用户自定义application.yml或application.properties,触发监听器,装备好广播环境
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
        //为当前应用绑定环境
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = this.convertEnvironment((ConfigurableEnvironment)environment);
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }
    //构建并返回对应环境
    private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;
        } else {
            switch(this.webApplicationType) {
            case SERVLET:
                return new ApplicationServletEnvironment();
            case REACTIVE:
                return new ApplicationReactiveWebEnvironment();
            default:
                return new ApplicationEnvironment();
            }
        }
    }

流程3:IoC容器创建,即创建应用程序上下文

context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);

创建上下文createApplicationContext()方法调用链

    protected ConfigurableApplicationContext createApplicationContext() {
        return this.applicationContextFactory.create(this.webApplicationType);
    }
    ... ...
    //主要是ApplicationContextFactory接口
    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
        try {
            Iterator var1 = SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader()).iterator();

            ConfigurableApplicationContext context;
            do {
                if (!var1.hasNext()) {
                    return new AnnotationConfigApplicationContext();
                }

                ApplicationContextFactory candidate = (ApplicationContextFactory)var1.next();
                context = candidate.create(webApplicationType);
            } while(context == null);

            return context;
        } catch (Exception var4) {
            throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var4);
        }
    };
    //接口
    ConfigurableApplicationContext create(WebApplicationType webApplicationType);
    //SERVLET实现
    static class Factory implements ApplicationContextFactory {
        Factory() {
        }

        public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
            return webApplicationType != WebApplicationType.SERVLET ? null : new AnnotationConfigServletWebServerApplicationContext();
        }
    }
    //REACTIVE实现
    static class Factory implements ApplicationContextFactory {
        Factory() {
        }

        public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
            return webApplicationType != WebApplicationType.REACTIVE ? null : new AnnotationConfigReactiveWebServerApplicationContext();
        }
    }

在这里插入图片描述
在这里插入图片描述
根据webApplicationType决定创建上下文的类型是AnnotationConfigServletWebServerApplicationContext还是AnnotationConfigReactiveWebServerApplicationContext

流程4:IoC容器的前置处理

this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

prepareContext方法详解

    private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    	//设置容器环境,如自定义配置、系统环境配置
        context.setEnvironment(environment);
        //执行后置处理
        this.postProcessApplicationContext(context);
        //执行初始化器
        this.applyInitializers(context);
        //广播容器准备完成事件,触发监听器
        listeners.contextPrepared(context);
        bootstrapContext.close(context);
        if (this.logStartupInfo) {
        	//打印启动信息
            this.logStartupInfo(context.getParent() == null);
            //打印profile信息
            this.logStartupProfileInfo(context);
        }
		//注册启动参数Bean,将容器的参数封装成Bean,注入容器
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //将springApplicationArguments注册到容器中
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
        	//注册springBootBanner
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }

        if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
        //不允许重复注册BeanDefinition
            ((AbstractAutowireCapableBeanFactory)beanFactory).setAllowCircularReferences(this.allowCircularReferences);
            if (beanFactory instanceof DefaultListableBeanFactory) {
                ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
            }
        }
		//若为懒加载,添加懒加载后置处理器
        if (this.lazyInitialization) {
            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
        }

        context.addBeanFactoryPostProcessor(new SpringApplication.PropertySourceOrderingBeanFactoryPostProcessor(context));
        //获取启动类指定的参数
        Set<Object> sources = this.getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //加载启动类,并注入容器
        this.load(context, sources.toArray(new Object[0]));
        //发布容器已加载事件,触发监听器
        listeners.contextLoaded(context);
    }
     //执行后置处理
    protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
        if (this.beanNameGenerator != null) {
            context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator);
        }

        if (this.resourceLoader != null) {
            if (context instanceof GenericApplicationContext) {
                ((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);
            }

            if (context instanceof DefaultResourceLoader) {
                ((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());
            }
        }

        if (this.addConversionService) {
            context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
        }

    }
  1. postProcessApplicationContext()进行后置处理
    protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    	//BeanFactory中注册BeanNameGenerator
        if (this.beanNameGenerator != null) {
            context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator);
        }

        if (this.resourceLoader != null) {
            if (context instanceof GenericApplicationContext) {
                ((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);
            }

            if (context instanceof DefaultResourceLoader) {
                ((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());
            }
        }
		//BeanFactory中注册ConversionService
        if (this.addConversionService) {
            context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
        }

    }
  1. applyInitializers()执行初始化器
    protected void applyInitializers(ConfigurableApplicationContext context) {
        Iterator var2 = this.getInitializers().iterator();
		//SpringApplication构造器中初始化了各种ApplicationContextInitializer
        while(var2.hasNext()) {
            ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
            Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
            Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
            initializer.initialize(context);
        }

    }
  1. getAllSources()和load()加载启动类并注入容器
    public Set<Object> getAllSources() {
        Set<Object> allSources = new LinkedHashSet();
        if (!CollectionUtils.isEmpty(this.primarySources)) {
        	//获取启动类
            allSources.addAll(this.primarySources);
        }

        if (!CollectionUtils.isEmpty(this.sources)) {
            allSources.addAll(this.sources);
        }

        return Collections.unmodifiableSet(allSources);
    }
    //启动类加入IoC容器中
    protected void load(ApplicationContext context, Object[] sources) {
        if (logger.isDebugEnabled()) {
            logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
        }

        BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
        //设置BeanNameGenerator
        if (this.beanNameGenerator != null) {
            loader.setBeanNameGenerator(this.beanNameGenerator);
        }
		//设置ResourceLoader
        if (this.resourceLoader != null) {
            loader.setResourceLoader(this.resourceLoader);
        }
		//设置Environment
        if (this.environment != null) {
            loader.setEnvironment(this.environment);
        }
		//加载
        loader.load();
    }
  1. contextLoaded()广播事件
    void contextLoaded(ConfigurableApplicationContext context) {
        this.doWithListeners("spring.boot.application.context-loaded", (listener) -> {
            listener.contextLoaded(context);
        });
    }
    //触发监听者
    private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction) {
        this.doWithListeners(stepName, listenerAction, (Consumer)null);
    }
    //触发监听者
    private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) {
        StartupStep step = this.applicationStartup.start(stepName);
        this.listeners.forEach(listenerAction);
        if (stepAction != null) {
            stepAction.accept(step);
        }

        step.end();
    }
    //广播事件
    public void contextLoaded(ConfigurableApplicationContext context) {
        ApplicationListener listener;
        for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
            listener = (ApplicationListener)var2.next();
            if (listener instanceof ApplicationContextAware) {
                ((ApplicationContextAware)listener).setApplicationContext(context);
            }
        }

        this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
    }

流程5: IoC容器的刷新,即刷新应用程序上下文

    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }

        this.refresh(context);
    }

    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            //刷新上下文
            this.prepareRefresh();
            //初始化BeanFactory,解析XML
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired 
            this.prepareBeanFactory(beanFactory);

            try {
            	//提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                //激活各种BeanFactory处理器
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注册拦截Bean创建的Bean处理器
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                //初始化上下文中的资源文件
                this.initMessageSource();
                //初始化上下文事件广播器
                this.initApplicationEventMulticaster();
                //给子类扩展初始化其他Bean
                this.onRefresh();
                //注册到广播器
                this.registerListeners();
                //设置转换器setConversionService,注册默认解析器addEmbeddedValueResolver,初始化非延迟加载的bean
                this.finishBeanFactoryInitialization(beanFactory);
                //通过spring的事件发布机制发布ContextRefreshedEvent事件
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }

                this.destroyBeans();
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }

流程6: IoC容器的后置处理

	//默认空,可以自定义
    protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
    }

流程7: 监听器启动完成

listeners.started(context, timeTakenToStartup);

流程8:执行Runners

    private void callRunners(ApplicationContext context, ApplicationArguments args) {
        List<Object> runners = new ArrayList();
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        AnnotationAwareOrderComparator.sort(runners);
        Iterator var4 = (new LinkedHashSet(runners)).iterator();

        while(var4.hasNext()) {
            Object runner = var4.next();
            //ApplicationRunner
            if (runner instanceof ApplicationRunner) {
                this.callRunner((ApplicationRunner)runner, args);
            }
			//CommandLineRunner
            if (runner instanceof CommandLineRunner) {
                this.callRunner((CommandLineRunner)runner, args);
            }
        }

    }

执行run()方法主流程总结

  1. 获取并启动运行过程监听器。
  2. 准备并构建环境。
  3. IoC容器的创建,即创建应用程序上下文。
  4. IoC容器的前置处理,即准备上下文。
  5. IoC容器的刷新,即刷新应用程序上下文。
  6. IoC容器的后置处理。
  7. 监听器启动完成。
  8. 执行Runners。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/642424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能的崛起:将导致大量工人流离失所

人工智能&#xff08;AI&#xff09;正在迅猛发展&#xff0c;并且已经开始改变世界。过去5到10年间&#xff0c;AI取得了巨大的进步&#xff0c;在某些领域甚至达到了人类水平&#xff0c;例如语音识别。AI的应用范围越来越广泛&#xff0c;其影响已经渗透到社会的方方面面。 …

DataSecurity Plus:强大的企业数据安全解决方案

企业数据安全是当今数字化时代中至关重要的一个议题。随着企业数字化转型的加速和数据泄露事件的频繁发生&#xff0c;保护和管理企业数据变得愈发关键。在这个背景下&#xff0c;DataSecurity Plus作为一款领先的数据安全解决方案&#xff0c;为企业提供了强大的保护机制和全面…

Deeplearing.AI 课程笔记(DLAI)

课程地址&#xff1a; https://learn.deeplearning.ai/chatgpt-prompt-eng OpenAI & Deeplearing.ai Lesson 2&#xff1a;准则 Prompting 的两个基本原则&#xff1a; write clear and specific instructions&#xff0c;第一原则是写清楚提示并给出具体说明to give t…

频谱分辨率、功率密度谱psd

问题&#xff1a; 频谱分辨率的作用是什么&#xff1f; 如频谱分辨率为3HZ,其物理意义是什么 功率密度谱是什么&#xff1f; 功率密度谱和功率的关系是什么&#xff1f; 频率分辨率的定义 DFT后频域相邻刻度之间的实际频率之差&#xff0c;还一般解释为能够分辨出的两个最小的…

Zotero PDF翻译插件自定义翻译功能实现

Zotero PDF翻译插件自定义翻译功能实现 一 需求二、实现演示三、Zetero翻译插件的功能定制3.1 开发环境3.2 开发步骤3.3 插件开发实现3.3.1 添加服务3.3.2 编写任务处理程序3.3.3 导入任务处理程序3.3.4 添加服务名称3.3.5 构建 四、服务器的开发4.1 环境4.2 代码实现 一 需求 …

java开发——shell编程

java开发——shell编程 shell是什么东西&#xff1f;java程序员为什么要学习Shell?Shell的解析器第一个Shell脚本Shell中的变量Shell的运算符Shell的条件判断Shell的if语句Shell的case语句Shell的for语句Shell的while语句Shell控制台输入Shell的系统函数Shell自定义函数Shell工…

MySQL InnoDB集群部署及管理全教程(二)

MySQL InnoDB集群部署及管理全教程&#xff08;一&#xff09;_Doker 多克的博客-CSDN博客 四、 部署生产 InnoDB 集群 在生产环境中工作时&#xff0c;组成InnoDB集群的MySQL服务器实例作为网络的一部分在多台主机上运行&#xff0c;而不是在第6.8节“AdminAPI MySQL Sandbo…

Unsupervised Learning(无监督学习)

目录 Introduction Clustering&#xff08;聚类&#xff09; Dimension Reduction&#xff08;降维&#xff09; PCA&#xff08;Principle component analysis&#xff0c;主成分分析&#xff09; Word Embedding&#xff08;词嵌入&#xff09; Matrix Factorization(矩…

Linux之用户管理

目录 Linux之用户管理 添加新用户 --- useradd命令 语法格式 常用选项 案例 为用户账号设置密码 -- passwd 语法格式 选项及作用 案例 修改用户属性 --- usermod命令 语法格式 选项及作用 案例 删除用户账号 --- userdel命令 语法格式 选项及作用 案例 用户切换 …

imu绘制轨迹

本文作者感谢武汉大学卫星导航定位技术研究中心多源智能导航实验室(i2Nav)牛小骥教授团队开源的KF-GINS软件平台。 首先声明&#xff0c;仅仅是实现&#xff0c;实际应用意义不大 这套算法利用EKF更新误差并且补偿到状态更新&#xff0c;如果没有gps信号时&#xff0c;利用im…

jetpack compose —— Card

jetpack compose Card 组件提供了一种简单而强大的方式来呈现卡片式的用户界面。 一、什么是 Card 组件 二、基本用法 三、属性和修饰符 四、嵌套使用和复杂布局 一、什么是 Card 组件 Card 是 Jetpack Compose 中的一个常用组件&#xff0c;用于呈现卡片式的用户界面。它…

量化投资 现代投资组合理论(MPT)

量化投资 现代投资组合理论&#xff08;MPT&#xff09; 问题&#xff1a;构建投资组合&#xff0c;达到目标收益率的同时拥有最小的 risk exposure. 有 J J J 个可交易证券&#xff0c;期望收益率为 R [ R 1 , ⋯ , R j ] T R[R_1,\,\cdots,\,R_j]^T R[R1​,⋯,Rj​]T&…

小红书数据洞察!父亲节将临,3大种草方式打动消费者

父亲节即将来临&#xff0c;各大社交平台陆陆续续开始讨论。品牌自然也不会错过此机&#xff0c;走心宣传。那么&#xff0c;今年的父亲节&#xff0c;有哪些热门内容呢&#xff1f;品牌如何点燃消费热情、提升形象&#xff1f;通过小红书数据和关键词分析&#xff0c;我们进一…

基于阿里云 Serverless 容器服务轻松部署企业级 AI 应用

作者&#xff1a;元毅、坤仑 数禾科技 AI 模型服务基于云原生架构&#xff0c;为不同业务环节提供智能决策支持。随着业务的快速发展&#xff0c;摆在数禾面前的难题是支撑模型计算的底层应用资源无法根据请求量来调整机器资源支持运算能力。同时&#xff0c;随着模型在线推理…

医疗行业的新选择:智能医疗管理模板

随着社会的发展&#xff0c;医疗行业也在不断地进步与发展&#xff0c;信息化已经成为医疗行业的重要一环。智能医疗管理应用作为新型医疗管理工具&#xff0c;已经成为中小型医院、门诊、美容机构等企业的必备软件之一。该应用包括患者管理、预约管理、诊断管理、住院管理、财…

Qt推荐的多线程的理解

目的 在Qt4.8之后&#xff0c;Qt多线程的写法最好还是通过QObject来实现&#xff0c;和线程的交互通过信号和槽(实际上其实是通过事件)联系。 用QObject来实现多线程有个非常好的优点&#xff0c;就是默认就支持事件循环&#xff08;Qt的许多非GUI类也需要事件循环支持&#x…

js执行顺序:

这篇笔记摘录来源&#xff1a; &#x1f449;我是javascript&#xff0c;2分钟彻底弄懂我的执行机制&#xff1f;【JavaScript教程】_哔哩哔哩_bilibili &#x1f449;js执行顺序_前端小白&#xff0c;请多指教的博客-CSDN博客 目录 面试题&#xff1a; 一、单线程 二、…

十年软件测试经验,我的成长之道

有很多小伙伴问&#xff0c;测试职业的天花板是不是很低&#xff1f; 在回答这个问题之前&#xff0c;我想请大家先想一下&#xff0c;当初自己为什么会选择测试这个职业&#xff1f;入门门槛低&#xff1f;不需要写代码&#xff1f;工作比开发轻松&#xff1f;还是其他。这个…

科技政策 | 工业和信息化部办公厅关于组织申报2023年跨行业跨领域工业互联网平台的通知

原创 | 文 BFT机器人 6月1日工业和信息化部办公厅发布关于组织申报2023年跨行业跨领域工业互联网平台的通知&#xff1b;旨在贯彻《国务院关于深化“互联网先进制造业”发展工业互联网的指导意见》&#xff0c;落实《工业互联网创新发展行动计划&#xff08;2021-2023年&#…

还有多少公司在使用H5?不怕被破解吗?

H5还有人在用吗 近几天&#xff0c;老板让我调查一下现在市面上H5的使用现状。粗略地调查了一下&#xff0c;发现现在使用H5的真不多了&#xff0c;但是还是有人在用H5的&#xff0c;原因无非一是成本低&#xff0c;相比户外广告&#xff0c;H5制作费用根本不值一提&#xff1…