Spring boot外部配置(配置中心化)详解
前言 在项目中为了灵活配置,我们常采用配置文件,常见的配置文件就比如xml和properties,springboot允许使用properties和yaml文件作为外部配置。现在编译器对于yaml语言的支持还不够好,目前还是使用properties文件作为外部配置。 在Spring cloud config出来之前,自己实现了基于ZK的配置中心,杜绝了本地properties配置文件,原理很简单,只是重载了PropertyPlaceholderConfigurer的 /** * 重载合并属性实现 * 先加载file properties, 然后并入ZK配置中心读取的properties * * @return 合并后的属性集合 * @throws IOException 异常 */ @Override protected Properties mergeProperties() throws IOException { Properties result = new Properties(); // 加载父类的配置 Properties mergeProperties = super.mergeProperties(); result.putAll(mergeProperties); // 加载从zk中读取到的配置 Map<String,String> configs = loadZkConfigs(); result.putAll(configs); return result; } 这个实现在spring项目里用起来还是挺顺手的,但是近期部分spring-boot项目里发现这种placeholder的实现跟spring boot的 也就是属性没有被resolve处理,用@Value的方式确可以读到,但是@Value配置起来如果属性多的话还是挺繁琐的,还是倾向用@ConfigurationProperties的prefix,于是看了下spring boot的文档发现 PropertySource order: * Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active). * @TestPropertySource annotations on your tests. * @SpringBootTest#properties annotation attribute on your tests. * Command line arguments. * Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property) * ServletConfig init parameters. * ServletContext init parameters. * JNDI attributes from java:comp/env. * Java System properties (System.getProperties()). * OS environment variables. * A RandomValuePropertySource that only has properties in random.*. * Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants) * Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants) * Application properties outside of your packaged jar (application.properties and YAML variants). * Application properties packaged inside your jar (application.properties and YAML variants). * @PropertySource annotations on your @Configuration classes. * Default properties (specified using SpringApplication.setDefaultProperties). 不难发现其会检查Java system propeties里的属性,也就是说,只要把mergerProperties读到的属性写入Java system props里即可,看了下源码,找到个切入点 /** * 重载处理属性实现 * 根据选项,决定是否将合并后的props写入系统属性,Spring boot需要 * * @param beanFactoryToProcess * @param props 合并后的属性 * @throws BeansException */ @Override protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,Properties props) throws BeansException { // 原有逻辑 super.processProperties(beanFactoryToProcess,props); // 写入到系统属性 if (writePropsToSystem) { // write all properties to system for spring boot Enumeration<?> propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { String propertyName = (String) propertyNames.nextElement(); String propertyValue = props.getProperty(propertyName); System.setProperty(propertyName,propertyValue); } } } 为避免影响过大,设置了个开关,是否写入系统属性,如果是spring boot的项目,就开启,这样对线上非spring boot项目做到影响最小,然后spring boot的 具体代码见: @Override public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException { ConfigurationProperties annotation = AnnotationUtils .findAnnotation(bean.getClass(),ConfigurationProperties.class); if (annotation != null) { postProcessBeforeInitialization(bean,beanName,annotation); } annotation = this.beans.findFactoryAnnotation(beanName,annotation); } return bean; } 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |