首页 > 其他分享 >SpringBoot启动

SpringBoot启动

时间:2023-12-15 15:57:31浏览次数:48  
标签:SpringBoot beanFactory 启动 listeners environment bean context 上下文

springBoot启动全流程如下所示:

框架初始化,完成相关配置:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }

 执行run方法:

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

springBoot环境准备:

1 Devtools全局配置  2 测试环境@TestPropertySource注解  3 测试环境properties属性  4 命令行参数  5 SPRING_APPLICATION_JSON属性  6 ServletConfig初始化参数  7 ServletContext初始化参数  8JNDI属性  9 JAVA系统属性  10 操作系统环境变量  11 RandomValuePropertySource随机值属性  12 jar包外的application-{profile}.properties  13 jar包内的application-{profile}.properties  14 jar包外的application.properties  15 14 jar包内的application.properties  16 @PropertySource绑定配置  17 默认属性

private ConfigurableEnvironment prepareEnvironment(
            SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
        // Create and configure the environment
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        configureEnvironment(environment, applicationArguments.getSourceArgs());
        listeners.environmentPrepared(environment);
        bindToSpringApplication(environment);
        if (!this.isCustomEnvironment) {
            environment = new EnvironmentConverter(getClassLoader())
                    .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
        }
        ConfigurationPropertySources.attach(environment);
        return environment;
    }

环境准备流程图解析:

准备上下文:

private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        postProcessApplicationContext(context);
        //遍历调用Initializer的Initilize方法
        applyInitializers(context);
        //发送ApplicationContextInitializedEvent事件
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        // Add boot specific singleton beans
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //注册springApplicationArguments
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            //springBootBanner
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        //加载sources
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[0]));
        //发送ApplicationPreparedEvent事件
        listeners.contextLoaded(context);
    }

刷新上下文

obtainFreshBeanFactory方法内部通过调用loadBeanDefinitions方法完成了bean定义的加载。

PrepareBeanFactory内部配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器postProcessors.

postProcessBeanFactory方法允许在bean没有实例化前允许修改应用上下文的内部beanFactory, 允许注册特殊的beanPostProcessors

invokeBeanFactoryPostProcessors方法实例化并调用所有注册的BeanFactoryPostProcessor bean

finishBeanFactoryInitialization方法实例化所有非惰性加载单例bean, 通过defaultListableBeanFactory的preInstantiateSingletons实例化单例bean,具体创建由abstractBeanFactory的getBean方法完成,从这里开始就和spring实例化bean有些类似了。

private void refreshContext(ConfigurableApplicationContext context) {
        refresh(context);
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            }
            catch (AccessControlException ex) {
                // Not allowed in some environments.
            }
        }
    }

    protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext) applicationContext).refresh();
    }

    //所属类:ApplicationContext
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //准备刷新此上下文。
            prepareRefresh();
            //告诉子类刷新内部bean工厂
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //准备bean工厂以便在此上下文中使用。
            prepareBeanFactory(beanFactory);
            try {
                //允许在上下文子类中对bean工厂进行后处理。
                //在标准初始化之后修改应用程序上下文的内部bean工厂。
                //所有的bean定义都将被加载,但还没有任何bean被实例化。这允许在某些ApplicationContext实现中注册特殊的BeanPostProcessors
                postProcessBeanFactory(beanFactory);
                //调用在上下文中注册为bean的工厂处理器(beanFactoryPostProcessor)
                invokeBeanFactoryPostProcessors(beanFactory);
                //注册拦截bean创建的bean处理器。
                registerBeanPostProcessors(beanFactory);
                //初始化此上下文的消息源。
                initMessageSource();
                //初始化此上下文的事件多播。
                initApplicationEventMulticaster();
                //初始化特定上下文子类中的其他特殊bean。
                onRefresh();
                //检查侦听器bean并注册它们。
                registerListeners();
                //实例化所有剩余的(非惰性init)singleton。
                finishBeanFactoryInitialization(beanFactory);
                //最后一步:发布相应的事件。
                finishRefresh();
            }
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                //销毁已创建的singleton以避免挂起资源。
                destroyBeans();
                cancelRefresh(ex);
                throw ex;
            }
            finally {
                //重置Spring核心中的常见内省缓存,因为我们可能再也不需要单例bean的元数据了。。。
                resetCommonCaches();
            }
        }
    }

标签:SpringBoot,beanFactory,启动,listeners,environment,bean,context,上下文
From: https://www.cnblogs.com/mtjb1dd/p/17903082.html

相关文章

  • python 脚本的启动模式(python -m以模块方式启动)
    今天再看python的项目时,发现GitHub中给出的python脚本的执行格式是python-mpipinstallsomepackage。于是开始了python模式启动之旅。其中很多相关借鉴了该博客,同时感谢博主:http://www.cnblogs.com/xueweihan/p/5118222.html什么是python启动模块:通过python启动一个库中......
  • springcloudalibabada搭建过程中springboot启动卡住起不来 (Started MoonceProviderApp
    如下图一样springcloudAlibaba在创建新模块之后启动新模块没有注册到nacos上,而是直接卡住起不来原因 原因是:引入了错误的web包: 解决办法:引入相应的 spring-boot-starter-web包:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot......
  • VMware Workstation 17中设置虚拟机开机自启动
    VMwareWorkstation17中设置虚拟机开机自启动的步骤如下:打开VMwareWorkstation17。在左侧导航栏点击配置自动启动虚拟机。然后选择要自动启动的虚拟机并配置启动顺序,点击确定。设置自动启动服务。打开任务管理器,点击服务,找到VmwareAutostartService,右键,点击开始。找到VMware......
  • Seata 启动报错:[imeoutChecker_1] i.s.c.r.netty.NettyClientChannelManager : no av
    Seata启动报错:[imeoutChecker_1]i.s.c.r.netty.NettyClientChannelManager:noavailableservertoconnect.1.问题2.解决【application.xml和file.conf参数要相对应】......
  • 启动Docker服务报错
    启动Docker服务报错如下Jobfordocker.servicefailedbecausethecontrolprocessexitedwitherrorcode.See"systemctlstatusdocker.service"and"journalctl-xe"fordetails.使用命令journalctl-xe查看解决方法一、关闭防火墙或者selinux1、关闭防火墙system......
  • Docker查看容器的启动命令
    安装第三方包:get_command_4_run_containerdockerpullcucker/get_command_4_run_container执行命令:dockerrun--rm-v/var/run/docker.sock:/var/run/docker.sockcucker/get_command_4_run_container[容器名称]/[容器ID]可以将其封装为一个别名echo"aliasget_run_comm......
  • 【STM32】STM32启动流程
    概述从上电复位到main函数的过程主要由以下步骤:1.初始化堆栈指针SP=_initial_sp,初始化PC指针=Reset_Handler2.初始化中断向量表3.配置系统时钟4.调用C库函数_main初始化用户堆栈,然后进入main函数1.STM32的启动模式STM32的启动模式决定了向量表的位置,STM32有三种启动模式:(......
  • 创建一个Redis集群的启动命令并启动
    第一步:进入到存放集群的目录里cd/opt/cluster如下图[红线圈中的目录]:第二步:在此目录创建sh文件[示例为start.sh],并打开编辑vimstart.sh第三步:在文件中,写入要执行的所有Redis端口命令`redis-server/opt/cluster/6001/redis.confredis-server/opt/cluster/6002/redis.c......
  • SpringBoot+MyBatis-Plus没有扫描到Mapper的问题
    一、问题:WARN22052---[      main]ConfigServletWebServerApplicationContext: NoMyBatismapperwasfoundin'[xxx.xxx.xxxx]'package.Pleasecheckyourconfiguration.WARN22052---[      main]ConfigServletWebServerApplicationConte......
  • springboot032 图书馆管理系统-计算机毕业设计源码+LW文档
    摘 要随着社会的发展,计算机的优势和普及使得阿博图书馆管理系统的开发成为必需。阿博图书馆管理系统主要是借助计算机,通过对图书借阅等信息进行管理。减少管理员的工作,同时也方便广大用户对所需图书借阅信息的及时查询以及管理。阿博图书馆管理系统的开发过程中,采用B/S架构,主......