复制
预备环境其实就做了下面几件事情:
- 创建一个
ConfigurableEnvironment
类型的配置环境 - 将配置环境实例
ConfigurableEnvironment
与SpringApplication启动类实例绑定到一个Binder
对象中去 - 上一步的 绑定属性的过程会去解析属性占位符,并按照配置环境配置的转换服务转转绑定结果 , 如果绑定成功或失败都会有对应的事件处理方法
SpringApplication#run
方法的context = this.createApplicationContext();
这行代码的具体实现,进入SpringApplication#createApplicationContext
方法体,源码如下:protected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {// 若启动类的应用上下文为空 , 则根据实例化SpringApplication启动类过程中推断出来的web应用类型加载对应的应用上下文类ApplicationContexttry {switch(this.webApplicationType) {case SERVLET:contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");break;case REACTIVE:contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");break;default:contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");}} catch (ClassNotFoundException var3) {throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);}}return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);}
复制从以上的源码可以看出创建应用上下文过程主要做了下面两件事情:
- 根据web应用类型加载对应的ApplicationContext实现类:
- 如果是Servlet应用程序则加载
AnnotationConfigServletWebServerApplicationContext
类作为应用上下文类; - 如果是Reactive应用程序则加载
AnnotationConfigReactiveWebServerApplicationContext
类作为应用上下文类; - 默认加载
AnnotationConfigApplicationContext
类作为应用上下文类
- 调用
BeanUtils
工具类实例化应用上下文类,并返回这个实例化的应用上下文对象
SpringApplication#run
方法的this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
这行代码,并进入SpringApplication#prepareContext
方法体内部private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 应用上下文设置配置环境属性context.setEnvironment(environment);// 应用上下文后置处理this.postProcessApplicationContext(context);// 申请初始化器this.applyInitializers(context);// 启动运行时监听器发布应用上下文预备事件listeners.contextPrepared(context);if (this.logStartupInfo) {// 记录日志this.logStartupInfo(context.getParent() == null);this.logStartupProfileInfo(context);}// 获取ConfigurableListableBeanFactory类型beanFactory,注意该类是个接口类ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 注册启动参数类型单例beanbeanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {// 注册PrintedBanner类型单例beanbeanFactory.registerSingleton("springBootBanner", printedBanner);}// 判断应用上下文中的beanFactory是否是一个DefaultListableBeanFactory类型的实例if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);// 设置是否允许覆写bean定义标识}if (this.lazyInitialization) {// 若是延迟初始化,则添加延迟初始化类型beanFactory后置处理器context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// 获取启动来源类集合 , 也就是我们项目中加上@SpringBootApplication注解的启动类集合Set<Object> sources = this.getAllSources();// 断言启动来源类不为空Assert.notEmpty(sources, "Sources must not be empty");// 加载应用上下文,这个方法会通过beanDefinationReader读取通过注解和xml配置的beanthis.load(context, sources.toArray(new Object[0]));// 启动监听器发布上下文完成加载事件listeners.contextLoaded(context);}
复制SpringApplication#postProcessApplicationContext方法
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {if (this.beanNameGenerator != null) {context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator); // 应用上下文中的beanFactory注册单例BeanNameGenerator bean}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(ApplicationConversionService.getSharedInstance());// 设置conversionService属性}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一次SpringBoot版本升级,引发的血案
- SpringBoot 03: 常用web组件 - - - 拦截器 + Servlet + 过滤器
- SpringBoot 02: 初识SpringBoot
- 超详细 SpringBoot 整合 Elasticsearch .md
- SpringBoot 01: JavaConfig + @ImportResource + @PropertyResource
- MindStudio模型训练场景精度比对全流程和结果分析
- 纸嫁衣4第三章交错通关流程图文攻略
- 纸嫁衣4第一章异途通关流程图文攻略-纸嫁衣4红丝缠第一章怎么过
- 纸嫁衣4第二章不期通关流程图文攻略-纸嫁衣4红丝缠第二章怎么过
- 洛克王国初秋落叶活动流程攻略-洛克王国初秋落叶怎么玩