SpringBoot中Spring应用上下文的准备有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
创新互联建站是一家集网站建设,元宝企业网站建设,元宝品牌网站建设,网站定制,元宝网站建设报价,网络营销,网络优化,元宝网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
Spring应用上下文的准备
首先,通过图 4-4 来整体了解一下 prepareContext 的核心功能及流程。
配合流程图,看一下 SpringApplication 中 prepareContext 方法源代码及功能注解。
private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunL isteners listeners , Applicat ionArguments applicat ionArguments, Bann er printedBanner) { //没置上下文的配置环境 context . setEnvironment (environment); //应用上下文后置处理 postProcessApplicationContext( context);//在 context 刷新之前,Appl icat ionContext Init ial izer 初始化 context applyInitializers(context); //通知监听器 context 准备完成,该方法以 上为上下文准备阶段,以下为上下文加载阶段 listeners . contextPrepared(context);//打印日志,启动 Profile if (this . logStartupInfo)- logStartupInfo(context . getParent() == nu1l); logStartupProfileInfo( context); } //获得 ConfigurableL istableBeanFactory 并炷册单例对象 ConfigurableL istableBeanFactory beanFactory = context . getBeanFactory(); beanFactory. registerSingleton("springApplicat ionArguments", applicationAr guments); if (printedBanner != null) { //注册打印日志对象 beanF actory. registerSingleton("springBootBanner", printedBanner); if (beanFactory instanceof DefaultlistableBeanFactory) { //没置是否允许覆盖炷册 ((DefaultListableBeanFactory) beanFactory) . setAllowBeanDefinitionOverriding(this . allowBeanDefinitionOverriding); //获取全部配置源,其中包含 primarySources 和 sources Set<0bject> sources = getAllSources(); Assert . notEmpty(sources, "Sources must not be empty"); //将 sources 中的 Bean 加载到 context 中 load(context, sources . toArray(new 0bject[0])); //遁知监听器 context 加载完成 listeners . contextLoaded(context); }
通过流程图和具体代码可以看出,在该方法内完成了两步操作:应用上下文的准备和加载。
下面我们针对具体的源代码进行详细讲解。
应用上下文准备阶段
在上下文准备阶段,主要有 3 步操作:对 context 设 置 environment、应用上下文后置处理和 ApplicationContextlnitializer 初始化 context 操作。
首先是对 context 设置 environment,代码和业务操作都很简单。
public void setEnvironment (ConfigurableEnvironment environment) { //设置 context 的 environment super. setEnvi ronment( environment); //设置 context 的 reader 属性的 conditionEvaluator 属性 this.reade er. settEnvironment(environment) ; //设置 context 的 scanner 属性的 environment 属性 this. scanner. setEnvi ronment ( envi ronment); }
随 后 , 便 是 进 行 Spring 应 用 上 下 文 的 后置处理 , 这 一 步 是 通 过postProcessApplicationContext 方法来完成的。
protected void postProcessApplicat ionContext (ConfigurableApplicat ionConEext context){ f (this. beanNameGenerator != null) { // 如果 beanNameGenerator 为 null, 则将当前的 beanNameGenerator 按照默认名字进 行注册 context . getBeanFactory(). regi sterSingleton( Annotat ionConfigUtils .CONF IGURATION BEAN NAME GENERATOR, this . beanNameGenerator); esourceLoader 为 null 时, 则根据 context 的类型分别进行 Resourceloader 和 CL assLoader 的设置 if (this .resourceLoader != null) { F (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context) . setResourcel oader(this . resource Loader); if (context instanceof DefaultResourceLoader) { ( (DefaultResourceLoader) context) . setClassLoader(this.resourceLoader. getClassLoader()); //如果为 true 则获取并没置转换服务 f (this .addConversionService) { context . getBeanFactory(). setConversionService( ApplicationConversionService . getSharedInstance()); }
postProcessApplicationContext 方 法 主 要 完 成 上 下 文 的 后 置 操 作 , 默 认 包 含beanNameGeneratorResourceL oader.ClassL oader 和 ConversionService 的设置。该方法可由子类覆盖实现,以添加更多的操作。
而在此阶段,beanNameGenerator 和 resourceL oader 都为 null,因此只操作了最后-一步的设置转换服务。
最后,在通知监听器 context 准备完成之前,通过 applylnitializers 方法对上下文进行初始化。
所使用的 ApplicationContextInitializer 正是我们在 SpringApplication 初始化阶段设置在itializers 变量中的值,只不过在通过 getlnitializers 方法获取时进行了去重和排序。
protected void applyInitializers(ConfigurableApplicat ionContext context) { /获取 Appl icat ionContextInitializer 集合并遍历 for (ApplicationContextInitializer initializer : getInitializers()) { //解析当前 initial izer.实现的 Appl icat ionContextInitializer 的泛型参数 Class requiredType = GenericTypeResolver . resolveTypeArgument( initializer . getClass(), ApplicationContextInitializer.class); 1 断言判断所需类似是否与 context 类型匹配 Assert. isInstanceOf(requiredType, context, "Unable to call initialize r."); // 初始化 context initializer. initialize(context); } }
完成以上操作之后,程序便调用 SpringApplicationRunListeners 的 contextPrepared 方法通知监听器,至此第一阶段的准备操作完成。
应用上下文加载阶段
应用上下文加载阶段包含以下步骤:打印日志和 Profile 的设置、设置是否允许覆盖注册、获取全部配置源、将配置源加载入上下文、通知监控器 contex 加载完成。
首先进入应用上下文加载阶段的操作为打印日志和 Profile 的设置,对此不展开讲解。随后,便是获得 ConfigurableL istableBeanFactory 并注册单例对象,注册的单例对象包含:
ApplicationArguments 和 Banner。 当 BeanFactory 为 DefaultL istableBeanFactory 时,进入设置是否允许覆盖注册的处理逻辑。
此处需注意的是,当进行了 ApplicationArguments 类单例对象的注册之后,也就意味着我们在使用 Spring 应用上下文的过程中可以通过依赖注入来使用该对象。
@Resource private ApplicationArguments applicat ionArguments;
完成以.上操作后,便进入配置源信息的处理阶段,这一步通过 getAllSources 方法来对配置源信息进行合并操作。
public Set