复制
预备环境其实就做了下面几件事情:
- 创建一个
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);}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一次SpringBoot版本升级,引发的血案
- 个人办理社保的流程是怎样的 个人怎么交社保
- 回门酒参加的都是谁 回门酒的流程
- 88vip双十一大额消费券领取流程2022 淘宝88vip双十一大额优惠券使用规则
- SpringBoot 03: 常用web组件 - - - 拦截器 + Servlet + 过滤器
- 房屋确权必须是户主吗 房屋确权的办理流程
- 公寓能不能抵押 房产证抵押贷款流程是什么
- SpringBoot 02: 初识SpringBoot
- 二手房网签注意事项 二手房网签流程
- 买房网签之后还有什么流程