SpringBoot原理
SpringBoot原理Spring原理【Spring注解】,SpringMVC原理,自动配置原理,SpringBoot原理1.SpringBoot启动过程启动过程创建SpringApplication—【new SpringApplication(primarySources)】保存一些信息判断当前的应用的类型。ClassUtils Servletspring5中是BootstrapRegist
SpringBoot原理
- Spring原理【Spring注解】,SpringMVC原理,自动配置原理,SpringBoot原理
1.SpringBoot启动过程
-
启动过程
-
创建SpringApplication—【new SpringApplication(primarySources)】
- 保存一些信息
- 判断当前的应用的类型。ClassUtils Servlet
- spring5中是BootstrapRegistryInitializer::去spring.factories文件中找org.springframework.boot.BootstrapRegistryInitializer【旧版是bootstrappers:初始启动引导器(List< Bootstraper>) 】
- 找ApplicationContextInitializer:去spring.factories找ApplicationContextInitializer
- List<ApplicationContextInitializer<?>> initializer
- 找到ApplicationListener;应用监听器,作用是监听当前引用状态。去spring.factories找ApplicationListener
- List<ApplicationListener<?>> listeners
-
运行SpringApplication
- StopWatch
- 记录应用的启动时间
- 创建引导上下文(Context环境)createBootstrapContext()
- 获取到所有之前的bootstrappers,遍历执行initialize()方法来完成对引导启动器上下文环境设置
- 让当前应用进入headless模式。java.awt.headless
- 获取所有RunListener(运行监听器)【为了方便所有Listener进行事件感知】
- getSpringFactoriesInstances去spring.factories找SpringApplicationRunlistener。
- 遍历所有SpringApplicationRunListener调用starting方法
- 相当于通知所有感兴趣系统正在启动过程的监听器,项目此时正在starting
- 保存命令行参数:ApplicationArguments
- 准备环境prepareEnvironment()
- 返回或创建基础环境信息对象。StandardServletEnvironment
- 配置环境信息对象
- 读取所有的配置源的配置属性值
- 绑定环境信息
- 监听器调用listener.environmentPrepared();通知所有的监听器当前环境准备完成
- 创建IOC容器(createApplicationContext())
- 根据项目类型(Servlet)创建容器;
- 当前会创建AnnotationConfigServletWebServerApplicationContext
- 准备ApplicationContext IOC容器的基本信息 prepareContext()
- 保存环境信息
- IOC容器的后置处理流程
- 应用初始化器,applyInitializers
- 遍历所有的ApplicationContextInitializer。调用initialize()方法,来对ioc容器进行初始化扩展功能
- 遍历所有的listener调用contextPrepared。EventPublishRunListener;通知所有的监听器contextPrepared
- 所有的监听器,调用contextLoaded,通知所有的监听器contextLoaded
- 刷新IOC容器,refreshContext
- 创建容器中的所有组件(Spring注解)
- 容器刷新完成后工作?afterRefresh
- 所有监听器掉员工listener.started(context):通知所有监听器started事件
- 调用所有runners;callRunners()
- 获取容器中的AppllicationRunner
- 获取容器中的CommandLineRunner
- 合并所有runner并按照@Order进行排序
- 遍历所有合并并且排序后的Runner,调用这些runner的run()方法
- 如果以上有异常
- 调用Listener的failed
- 调用所有监听的running方法listeners.running(context);通知所有的监听器running
- running如果有问题,继续通知failer。调用所有listener的failed;通知所有的监听器failed
2.SpringBoot启动过程-创建SpringApplication【Spring应用】
-
调用new SpringApplication(primarySources)–【primarySources为主配置类】
-
初始化属性
-
属性名 作用 resourceLoader 资源加载器 primarySources 主配置类 webApplicationType web应用类型,决定后续的IOC容器ApplicationContext
【Servlet–》AnnotationConfigServletWebServerApplicationContext】BootstrapRegistryInitializer 初始启动器,初始引导器 ApplicationContextInitializer IOC容器ApplicationContext的初始化引导器 ApplicationListener 应用监听器,作用是监听当前应用状态 mainApplicationClass 主方法main的所属类,主程序类有很多,只要找到第一个包含main方法的类就可以
-
-
@SuppressWarnings({ "unchecked", "rawtypes" }) public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { //设置资源加载器 this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); //设置主配置类,当前为HelloServiceSpringBootApplication this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //设置Web应用类型--当前为servlet this.webApplicationType = WebApplicationType.deduceFromClasspath(); //获取所有的初始化启动器 this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories(); //设置IOC容器ApplicationContext初始化引导器 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
3.SpringBoot启动过程–运行Spring应用 【SpringApplication】
-
通过调用springApplication.run(args),启动SpringBoot应用
-
涉及的类及其作用的说明
-
类 作用 获取方式 StopWatch 监听器,会调用stopWatch.start(),记录了spring应用在哪个时间启动的 DefaultBootstrapContext 默认的引导上下文, BootStrapRegistryInitializer 引导注册初始化器 从spring.factories文件中获取 ApplicationListener 监听SpringBoot启动容器过程中的事件 从spring.factories文件中获取 SpringApplicationRunListener spring应用运行监听器适配器,这个类内部包括了所有的applicationListener,监听spring应用的事件,来做事件分发,在SpringApplicationRunListener中,
会有一个SimpleApplicationEventMulticaster属性【应用事件分发器】,
调用SpringApplicationRunListener的starting方法,实际是通过eventMulticaster分发事件ApplicationStartingEvent
具体的实现类–》EventPublishingRunListener从spring.factories文件中获取 ApplicationRunner 回调run,自定义可以监控到listener.started()事件后的处理操作 通过@Component注入IOC容器 CommandLineRunner 回调run,自定义可以监控到listener.started()事件后的处理操作 通过@Component注入IOC容器
-
-
源码
-
public ConfigurableApplicationContext run(String... args) { //启动监听器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); //创建引导上下文 DefaultBootstrapContext bootstrapContext = createBootstrapContext(); ConfigurableApplicationContext context = null; //让当前应用进入headless模式 configureHeadlessProperty(); //获取所有运行监听器 SpringApplicationRunListeners listeners = getRunListeners(args); //遍历所有的RunListener,调用SpringApplicationRunListener的starting方法,通知所有监听器,当前项目正在starting listeners.starting(bootstrapContext, this.mainApplicationClass); try { //保存命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //准备运行时环境信息 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); //配置忽略的Bean信息 configureIgnoreBeanInfo(environment); //打印banner Banner printedBanner = printBanner(environment); //创建IOC容器ApplicationContext context = createApplicationContext(); //IOC容器ApplicationContext记录ApplicationStartup事件 context.setApplicationStartup(this.applicationStartup); //准备IOC容器的信息 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); //刷新IOC容器 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, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }
-
-
过程详解
-
StopWatch stopWatch = new StopWatch();
-
createBootstrapContext();创建引导上下文。
-
先创建一个DefaulteBootstrapContext,
-
遍历所有在创建SpringApplication时,从项目中所有META-INF/spring.factories配置的BootstrapRegistryInitializer,逐个调用BootstrapRegistryInitializer的initialize(DefaultBootstrapContext)方法,将DefaultBootstrapContext传入每个initialize()方法中
-
private DefaultBootstrapContext createBootstrapContext() { DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext)); return bootstrapContext; }
-
-
getRunListeners(args);获取所有运行监听器,从spring.factories文件中,获取SpringApplicationRunListener.class,内置事件分发器eventMulticaster,用于做各种事件的分发
-
private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup); }
-
new DefaultApplicationArguments(args); – 》保存命令行参数
-
prepareEnvironment(listeners, bootstrapContext, applicationArguments);准备运行时环境信息
-
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { // Create and configure the environment //创建基础环境信息对象 ConfigurableEnvironment environment = getOrCreateEnvironment(); //配置环境信息 configureEnvironment(environment, applicationArguments.getSourceArgs()); ConfigurationPropertySources.attach(environment); //通过applicationRunListener触发事件,环境信息准备完成 listeners.environmentPrepared(bootstrapContext, environment); DefaultPropertiesPropertySource.moveToEnd(environment); Assert.state(!environment.containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties."); //绑定 bindToSpringApplication(environment); if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } ConfigurationPropertySources.attach(environment); return environment; }
-
-
configureIgnoreBeanInfo(environment);配置忽略的Bean信息
-
printBanner(environment);:打印Banner
-
createApplicationContext();:创建IOC容器ApplicationContext,根据应用类型创建IOC容器,当前创建的是AnnotationConfigServletWebServerApplicationContext【因为webapplicationType=servlet】
-
ApplicationContextFactory DEFAULT = (webApplicationType) -> { try { switch (webApplicationType) { case SERVLET: return new AnnotationConfigServletWebServerApplicationContext(); case REACTIVE: return new AnnotationConfigReactiveWebServerApplicationContext(); default: return new AnnotationConfigApplicationContext(); } } catch (Exception ex) { throw new IllegalStateException("Unable create a default ApplicationContext instance, " + "you may need a custom ApplicationContextFactory", ex); } };
-
-
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);准备IOC容器的初始化上下文
-
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //容器设置环境配置 context.setEnvironment(environment); //应用上下文后置操作 postProcessApplicationContext(context); //应用初始化器,遍历调用所有ApplicationContextInitializer的initialize()方法,对IOC容器的进行初始化扩展功能 applyInitializers(context); //调用ApplicationRunListener的contextPrepared上下文准备完成事件 listeners.contextPrepared(context); //调用引导信息上下文关闭事件 bootstrapContext.close(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans //创建BeanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //将启动命令作为Bean注入BeanFactory beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } //判断BeanFactory是否是DefaultListableBeanFactory,如果是调用setAllowBeanDefintionOverriding方法,允许bean定义重载 if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } //判断是否需要添加懒加载初始化Bean工厂后置处理器--LazyInitializationBeanFactoryPostProcessor if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[0])); //所有监听器调用contextLoaded,表示context加载完成 listeners.contextLoaded(context); }
-
例如ServletContextApplicationContextInitializer的initialize方法设置servletContext,设置上下文属性
-
public class ServletContextApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext>, Ordered { @Override public void initialize(ConfigurableWebApplicationContext applicationContext) { applicationContext.setServletContext(this.servletContext); if (this.addApplicationContextAttribute) { this.servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); } } }
-
-
-
refreshContext(context);刷新IOC容器,
- 其中onRefresh()方法被子类AnnotationConfigServletWebServerApplicationContext重写
- 在AnnotationConfigServletWebServerApplicationContext的onRefresh()方法中,会调用createWebServer()方法,来创建并启动WebServer
- 具体是通过从容器中获取到WebServerFactory,调用getWebServer()方法获取到WebServer,并启动
-
afterRefresh(context, applicationArguments);刷新容器后操作
-
listeners.started(context);调用监听器,触发应用已启动事件
-
callRunners(context, applicationArguments);调用所有的runners,获取容器中的ApplicationRunner和CommandRunner
-
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); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
-
handleRunFailure(context, ex, listeners); 如果有异常,调用监听器的failed事件,进行分发。然后进入异常日志记录,抛出异常
-
private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception, SpringApplicationRunListeners listeners) { try { try { handleExitCode(context, exception); if (listeners != null) { listeners.failed(context, exception); } } finally { reportFailure(getExceptionReporters(context), exception); if (context != null) { context.close(); } } } catch (Exception ex) { logger.warn("Unable to close ApplicationContext", ex); } ReflectionUtils.rethrowRuntimeException(exception); }
-
-
listener.running(context):调用触发所有监听器的running方法,通知监听器应用进入running方法,running方法在上述容器创建和初始化之后,如果在容器创建和初始化过程中出现异常,不影响listeners.running(),而listener.running出错的话,不会调用listener的failed()方法,会直接退出
-
更多推荐
所有评论(0)