2022-08-23  阅读(45)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.skjava.com/series/article/1805954434

在博客 【死磕 Spring】----- IOC 之 深入分析 PropertyPlaceholderConfigurer 中了解了 PropertyPlaceholderConfigurer 内部实现原理,她 允许我们在 XML 配置文件中使用占位符并将这些占位符所代表的资源单独配置到简单的 properties 文件中来加载 。这个特性非常重要,因为它我们对 Bean 实例属性的配置变得非常容易控制了,主要使用场景有:

  1. 动态加载配置文件,多环境切换
  2. 属性加解密

下面我们就第一个应用场景来做说明。

利用 PropertyPlaceholderConfigurer 实现多环境切换

在我们项目开发过程中,都会存在多个环境,如 dev 、test 、prod 等等,各个环境的配置都会不一样,在传统的开发过程中我们都是在进行打包的时候进行人工干预,或者将配置文件放在系统外部,加载的时候指定加载目录,这种方式容易出错,那么有没有一种比较好的方式来解决这种情况呢?有, 利用 PropertyPlaceholderConfigurer 的特性来动态加载配置文件,实现多环境切换

首先我们定义四个 Properties 文件,如下:

202202131351059511.png

内容如下:

            - application-dev.properties
            student.name=chenssy-dev
            
            - application-test.properties
            student.name=chenssy-test
            
            - application-prod.properties
            student.name=chenssy-prod

然后实现一个类,该类继承 PropertyPlaceholderConfigurer,实现 loadProperties(),根据环境的不同加载不同的配置文件,如下:

            public class CustomPropertyConfig extends PropertyPlaceholderConfigurer {
            
                private Resource[] locations;
            
                private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
            
                @Override
                public void setLocations(Resource[] locations) {
                    this.locations = locations;
                }
            
                @Override
                public void setLocalOverride(boolean localOverride) {
                    this.localOverride = localOverride;
                }
            
                /**
                 * 覆盖这个方法,根据启动参数,动态读取配置文件
                 * @param props
                 * @throws IOException
                 */
                @Override
                protected void loadProperties(Properties props) throws IOException {
                    if (locations != null) {
                        // locations 里面就已经包含了那三个定义的文件
                        for (Resource location : this.locations) {
                            InputStream is = null;
                            try {
                                String filename = location.getFilename();
                                String env = "application-" + System.getProperty("spring.profiles.active", "dev") + ".properties";
            
                                // 找到我们需要的文件,加载
                                if (filename.contains(env)) {
                                    logger.info("Loading properties file from " + location);
                                    is = location.getInputStream();
                                    this.propertiesPersister.load(props, is);
            
                                }
                            } catch (IOException ex) {
                                logger.info("读取配置文件失败.....");
                                throw ex;
                            } finally {
                                if (is != null) {
                                    is.close();
                                }
                            }
                        }
                    }
                }
            }

配置文件:

                <bean id="PropertyPlaceholderConfigurer" class="org.springframework.core.custom.CustomPropertyConfig">
                    <property name="locations">
                        <list>
                            <value>classpath:config/application-dev.properties</value>
                            <value>classpath:config/application-test.properties</value>
                            <value>classpath:config/application-prod.properties</value>
                        </list>
                    </property>
                </bean>
            
                <bean id="studentService" class="org.springframework.core.service.StudentService">
                    <property name="name" value="${student.name}"/>
                </bean>

在 idea 的 VM options 里面增加 -Dspring.profiles.active=dev,标志当前环境为 dev 环境。测试代码如下:

            ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
            
            StudentService studentService = (StudentService) context.getBean("studentService");
            System.out.println("student name:" + studentService.getName());

运行结果:

            student name:chenssy-dev

当将 -Dspring.profiles.active 调整为 test,则打印结果则是 chenssy-test,这样就完全实现了根据不同的环境加载不同的配置,如果各位用过 Spring Boot 的话,这个就完全是 Spring Boot 里面的 profiles.active 。

PropertyPlaceholderConfigurer 对于属性的配置非常灵活,就看怎么玩了。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文