【springboot(4) 启动过程及实现对bean动态代理源码分析】1.springboot启动过程分析
- springboot启动过程run方法:
public ConfigurableApplicationContext run(String... args) { //创建一个StopWatch对象并调用它的start方法,该类是Spring提供的一个计时器类 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; //设置系统属性java.awt.headless,这里设置为true,表示运行在服务器端 configureHeadlessProperty(); /** * 获取SpringApplicationRunListeners对象,这个对象是一个SpringBoot事件广播器的管理者, * 它主要是管理SpringApplicationRunListener对象的, * SpringApplicationRunListener接口规定了SpringBoot的生命周期,并在各个生命周期广播相应的事件 * springboot默认为EventPublishingRunListener * 具体可见另外一篇博文springboot(2)生命周期和监听器。 */ SpringApplicationRunListeners listeners = getRunListeners(args); //广播启动事件 listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //准备运行的环境,比如开发环境dev,测试环境test然后根据环境解析不同的配置文件,并广播环境准备事件 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); //打印SpringBoot的LOGO Banner printedBanner = printBanner(environment); //创建SpringBoot的上下文 判断当前是否是web环境, //如果是web程序,创建AnnotationConfigEmbeddedWebApplicationContext的实例, //否则创建AnnotationConfigApplicationContext的实例 context = createApplicationContext(); //创建FailureAnalyzers的对象,主要是用来处理启动时发生一些异常时的一些分析 analyzers = new FailureAnalyzers(context); //准备上下文 prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新上下文 refreshContext(context); afterRefresh(context, applicationArguments); //发送启动完成事件 listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } } |
- 准备运行的环境
private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // 检查之前设置的webEnvironment属性,如果是web程序,那么创建一个StandardServletEnvironment对象,否则创建StandardEnvironment对象 ConfigurableEnvironment environment = getOrCreateEnvironment(); //准备运行环境配置,根据环境,比如开发环境dev,加载相关配置文件 configureEnvironment(environment, applicationArguments.getSourceArgs()); //发布运行环境加载完毕的事件 listeners.environmentPrepared(environment); if (!this.webEnvironment) { environment = new EnvironmentConverter(getClassLoader()) .convertToStandardEnvironmentIfNecessary(environment); } return environment; } |
- 准备上下文:
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //设置上下文环境 context.setEnvironment(environment); //设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话) postProcessApplicationContext(context); //利用初始化器,对上下文做初始化 //具体可见另外一篇博文 springboot (3)应用上下文初始化器ApplicationContextInitializer applyInitializers(context); //发布上下文准备好的事件 listeners.contextPrepared(context); //打印启动日志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } //向上下文的beanFactory中注册一个singleton的bean,bean的名字是springApplicationArguments, //bean的实例是之前实例化的ApplicationArguments对象 context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); //向上下文的beanFactory中注册一个singleton的bean,bean的名字是springBootBanner,bean的实例就是这个printedBanner if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } //向上下文注册启动类的bean,也就是调用SpringApplication.run(Application.class, args); 的类,这里只有一个 Set |
- 刷新上下文
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //为刷新上下文信息做准备。例如清空缓存,初始化属性信息,验证必要的属性等 prepareRefresh(); //获取到beanFactory,把refreshed属性设置成true,表示已经刷新了,下次再刷新就会抛出异常,不允许重复刷新, //然后给beanFactory设置serializationId,就是之前通过ContextIdApplicationContextInitializer生成的id //然后通过getBeanFactory方法拿到上下文的beanFactory(之前创建上下文的时候,创建了一个DefaultListableBeanFactory对象) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //对beanFactory设置相关参数 prepareBeanFactory(beanFactory); try { //为beanFactory添加后置处理器WebApplicationContextServletContextAwareProcessor,并忽略ServletContextAware postProcessBeanFactory(beanFactory); //扫描路径下的所有类,如果被@Component等注解的类,生成BeanDefinition对象,并回调BeanFactoryPostProcessor后置处理器 invokeBeanFactoryPostProcessors(beanFactory); //注册bean的后置处理器,这些后置处理器将在bean的创建过程中被调用 registerBeanPostProcessors(beanFactory); //初始化上下文的消息源 initMessageSource(); //初始化事件广播器,springboot在广播事件的时候,默认是同步的,如果想要实现事件异步传播, //就需要自定义一个名叫applicationEventMulticaster的bean, //这里就是看是否有自定义的bean,如果有则用用户创建的,否则就用默认的。 initApplicationEventMulticaster(); //初始化其他特殊的bean,比如创建serverlet容器相关的bean(TomcatEmbeddedServletContainerFactory) onRefresh(); //想事件广播器中添加各种事件监听器 registerListeners(); //实例化所有单例bean finishBeanFactoryInitialization(beanFactory); //发布容器事件,结束刷新过程 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } |
- 对beanFactory设置相关参数prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //设置用于加载bean的类加载器 beanFactory.setBeanClassLoader(getClassLoader()); //设置可以解析bean表达式的 表达式解析器 (使用"#{xxx}"配置的属性) beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //添加属性注册器 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); //添加ApplicationContextAwareProcessor后置处理器 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //设置了6个忽略自动注入的接口,为什么要忽略呢?因为上一步添加的ApplicationContextAwareProcessor,会在bean初始化前后调用相应的方法, //而相应的方法里有如下6个设置对应的接口 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //设置了几个自动装配的特殊规则,如果注入的是BeanFactory类型,则注入beanFactory对象, //如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型,则注入当前对象(Spring上下文 - context) beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //注册ApplicationListenerDetector,应用监听检查器, //该检测器的主要作用是在bean初始化后,会检查该bean是否是ApplicationListener, //如果是,那么会验证它是否是单例,如果不是单例,那么删除singletonNames中对应的key,singletonNames中记录了bean的名称及是否是单例 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //注册几个特殊的bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } |
1.获取spring应用执行监听器(SpringApplicationRunListeners)
2.利用spring应用执行监听器广播启动事件
3.准备运行的环境(dev,test),根据环境解析不同的配置文件
3.1 检查webEnvironment属性,如果是web程序,那么创建一个StandardServletEnvironment对象,否则创建StandardEnvironment对象
3.2 准备运行环境配置,根据环境(dev,test),加载相关配置文件
3.3 利用spring应用执行监听器广播运行环境加载完毕的事件
4.创建spring应用上下文,如果是web程序,创建web应用上下文实例
5.准备spring应用上下文
5.1 利用spring初始化器,对上下文做初始化操作
5.2 利用spring应用执行监听器广播上下文准备好的事件
5.3 向beanFactory注册springApplicationArguments和springBootBanner单例bean
5.4 向上下文注册启动类的bean,也就是调用SpringApplication.run(Application.class, args); 的类
5.5 利用spring应用执行监听器广播上下文加载完毕事件
6.刷新spring应用上下文
6.1 为刷新上下文信息做准备。例如清空缓存,初始化属性信息,验证必要的属性等
6.2 获取应用上下文的beanFactory
6.3 对beanFactory设置相关参数
6.4 为beanFactory添加后置处理器WebApplicationContextServletContextAwareProcessor,并忽略ServletContextAware
6.5 调用beanFactory的后置处理器
6.6 注册bean的后置处理器,这些后置处理器将在bean的创建过程中被调用
6.7 初始化事件广播器(EventMulticaster),看是否有自定义的事件广播bean(applicationEventMulticaster),如果有则使用自定义的,否则就用默认的。
6.8 初始化其他特殊的bean,比如创建serverlet容器相关的bean
6.9 向事件广播器EventMulticaster中添加各种事件监听器
6.10 实例化所有单例bean
6.11 结束刷新,利用EventMulticaster广播上下文刷新完成事件
7.执行应用runner(或命令行runner)
8.利用spring应用执行监听器广播启动完成事件
推荐阅读
- 第五节:SpringBoot常用注解介绍
- 第四节:SpringBoot中web模版数据渲染展示
- SpringBoot2022【草稿】
- 聊聊springboot项目全局异常处理那些事儿
- 第一节:创建SpringBoot项目并运行HelloWorld
- springboot管理系统[基于员工角色和文件权限的分级的后台管理系统源码]
- SpringBoot之@ComponentScan和@SpringBootApplication扫描覆盖问题
- mybatis|记mybatis查询null字段导致的NPE
- SpringBoot|SpringBoot 整合 druid数据源
- springboot项目配置application添加图片映射 (windows and linux 都可使用)