热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringBoot的EnvironmentPostProcessor怎么用

今天小编给大家分享一下SpringBoot的EnvironmentPostProcessor怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所

今天小编给大家分享一下SpringBoot的EnvironmentPostProcessor怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    一、背景

    之前项目中用到了Apollo配置中心,对接Apollo配置中心后,配置中心的属性就可以在程序中使用了,那么这个是怎么实现的呢?配置中心的属性又是何时加载到程序中的呢?那么我们如果找到了这个是怎么实现的是否就可以 从任何地方加载配置属性配置属性的加解密功能呢

    二、需求

    SpringBoot的EnvironmentPostProcessor怎么用

    从上图中得知,我们的需求很简单,即我们自己定义的属性需要比配置文件中的优先级更高。

    三、分析

    1、什么时候向SpringBoot中加入我们自己的配置属性

    当我们想在Bean中使用配置属性时,那么我们的配置属性必须在Bean实例化之前就放入到Spring到Environment中。即我们的接口需要在 application context refreshed 之前进行调用,而 EnvironmentPostProcessor 正好可以实现这个功能。

    2、获取配置属性的优先级

    我们知道在 Spring中获取属性是有优先级的。
    比如我们存在如下配置属性 username

    ├─application.properties
    │   >> username=huan
    ├─application-dev.properties
    │   >> username=huan.fu

    那么此时 username 的值是什么呢?此处借用 Apollo的一张图来说解释一下这个问题。

    参考链接:https://www.apolloconfig.com/#/zh/design/apollo-design

    SpringBoot的EnvironmentPostProcessor怎么用

    Spring从3.1版本开始增加了ConfigurableEnvironmentPropertySource

    ConfigurableEnvironment
    • Spring的ApplicationContext会包含一个Environment(实现ConfigurableEnvironment接口)

    • ConfigurableEnvironment自身包含了很多个PropertySource

    PropertySource

    • 属性源

    • 可以理解为很多个Key - Value的属性配置

    由上方的原理图可知,key在最开始出现的PropertySource中的优先级更高,上面的例子在SpringBootusername的值为huan.fu

    3、何时加入我们自己的配置

    由第二步 获取配置属性的优先级 可知,PropertySource 越靠前越先执行,那么要我们配置生效,就必须放在越前面越好。

    SpringBoot的EnvironmentPostProcessor怎么用

    由上图可知,SpringBoot加载各种配置是通过EnvironmentPostProcessor来实现的,而具体的实现是ConfigDataEnvironmentPostProcessor来实现的。那么我们自己编写一个EnvironmentPostProcessor的实现类,然后在ConfigDataEnvironmentPostProcessor后执行,并加入到 Environment中的第一位即可。

    SpringBoot的EnvironmentPostProcessor怎么用

    四、实现

    1、引入SpringBoot依赖

    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.6.6
             
        
        com.huan.springcloud
        springboot-extension-point
        0.0.1-SNAPSHOT
        springboot-extension-point
        
            1.8
        
        
            
                org.springframework.boot
                spring-boot-starter-web
            
        
    

    2、在application.properties中配置属性

    vim application.properties
    username=huan

    3、编写自定义属性并加入Spring Environment中

    SpringBoot的EnvironmentPostProcessor怎么用

    注意:
    1、如果发现程序中日志没有输出,检查是否使用了slf4j输出日志,此时因为日志系统未初始化无法输出日志。解决方法如下:

    SpringBoot版本
    		>= 2.4 可以参考上图中的使用 DeferredLogFactory 来输出日志
    		< 2.4
    			1、参考如下链接 https://stackoverflow.com/questions/42839798/how-to-log-errors-in-a-environmentpostprocessor-execution
    			2、核心代码:
    				@Component
    				public class MyEnvironmentPostProcessor implements
    				        EnvironmentPostProcessor, ApplicationListener {
    				    private static final DeferredLog log = new DeferredLog();
    				    @Override
    				    public void postProcessEnvironment(
    				            ConfigurableEnvironment env, SpringApplication app) {
    				        log.error("This should be printed");
    				    }
    				    @Override
    				    public void onApplicationEvent(ApplicationEvent event) {
    				        log.replayTo(MyEnvironmentPostProcessor.class);
    				    }
    				}

    4、通过SPI使自定义的配置生效

    1、在 src/main/resources下新建META-INF/spring.factories文件

    SpringBoot的EnvironmentPostProcessor怎么用

    2、配置

    org.springframework.boot.env.EnvirOnmentPostProcessor=\
      com.huan.springcloud.extensionpoint.environmentpostprocessor.CustomEnvironmentPostProcessor

    5、编写测试类,输出定义的 username 属性的值

    @Component
    public class PrintCustomizeEnvironmentProperty implements ApplicationRunner {
    
        private static final Logger log = LoggerFactory.getLogger(PrintCustomizeEnvironmentProperty.class);
        @Value("${username}")
        private String userName;
        @Override
        public void run(ApplicationArguments args) {
            log.info("获取到的 username 的属性值为: {}", userName);
        }
    }

    6、运行结果

    SpringBoot的EnvironmentPostProcessor怎么用

    五、注意事项

    1、日志无法输出

    参考上方的 3、编写自定义属性并加入Spring Environment中提供的解决方案。

    2、配置没有生效检查

    • 检查EnvironmentPostProcessor的优先级,看看是否@Order或者Ordered返回的优先级值不对。

    • 看看别的地方是否实现了 EnvironmentPostProcessor或ApplicationContextInitializer或BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor等这些接口,在这个里面修改了 PropertySource的顺序。

    • 理解 Spring 获取获取属性的顺序 参考 2、获取配置属性的优先级

    3、日志系统如何初始化

    如下代码初始化日志系统

    org.springframework.boot.context.logging.LoggingApplicationListener

    以上就是“SpringBoot的EnvironmentPostProcessor怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程笔记行业资讯频道。


    推荐阅读
    • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
      本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
    • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
      在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
    • Spring源码解密之默认标签的解析方式分析
      本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
    • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
    • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
      本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
    • Activiti7流程定义开发笔记
      本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
    • Spring特性实现接口多类的动态调用详解
      本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
    • Voicewo在线语音识别转换jQuery插件的特点和示例
      本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
    • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
    • PDO MySQL
      PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
    • 一次上线事故,30岁+的程序员踩坑经验之谈
      本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
    • 解决IDEA配置xml文件头报错的方法
      本文介绍了解决IDEA配置xml文件头报错的方法,包括了具体的解决方案和步骤。通过本文的指导,读者可以轻松解决这个问题并正常使用IDEA进行开发工作。 ... [详细]
    • 本文提供了关于数据库设计的建议和注意事项,包括字段类型选择、命名规则、日期的加入、索引的使用、主键的选择、NULL处理、网络带宽消耗的减少、事务粒度的控制等方面的建议。同时还介绍了使用Window Functions进行数据处理的方法。通过遵循这些建议,可以提高数据库的性能和可维护性。 ... [详细]
    • 熟练掌握Spring Cloud,终于成为Java工程师的面试门槛 ... [详细]
    • 服务网关与流量网关
      一、为什么需要服务网关1、什么是服务网关传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关& ... [详细]
    author-avatar
    mobiledu2502883683
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有