博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring boot自定义加载yml实现,附源码解读
阅读量:5954 次
发布时间:2019-06-19

本文共 4984 字,大约阅读时间需要 16 分钟。

hot3.png

背景

昨天在对公司的微服务配置文件标准化的过程中,发现将原来的properties文件转为yml文件之后,微服务module中标记有@Configuration的配置类都不能正常工作了,究其原因,是由于@PropertySource属性默认只用于标记并告诉spring boot加载properties类型的文件,spring boot 2.0.0.RELEASE版的文档解释如下:

24.6.4 YAML ShortcomingsYAML files cannot be loaded by using the @PropertySource annotation. So, in the case that you need to load values that way, you need to use a properties file.

这段话的意思是说:

24.6.4 YAML 缺点YAML 文件不能用 @PropertySource 注解来标记加载。因此,在需要加载值的场景,你需要使用属性文件。

解决方法

解决这个问题并不难,我们只需要自定义一个yaml文件加载类,并在@PropertySource注解的factory属性中声明就可以。scala版实现代码如下,spring boot版本为2.0.0.RELEASE:

1、自定义yaml文件资源加载类

import org.springframework.boot.env.YamlPropertySourceLoaderimport org.springframework.core.env.PropertySourceimport org.springframework.core.io.support.{DefaultPropertySourceFactory, EncodedResource}/**  * yaml资源加载类  */class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory{  override def createPropertySource(name: String, resource: EncodedResource): PropertySource[_] = {    if (resource == null) {      super.createPropertySource(name, resource)    }    return new YamlPropertySourceLoader().load(resource.getResource.getFilename, resource.getResource, null)  }}

这个类继承自DefaultPropertySourceFactory类,并重写了createPropertySource方法。

2、引入@PropertySource注解并使用

import com.core.conf.YamlPropertyLoaderFactoryimport javax.persistence.EntityManagerFactoryimport javax.sql.DataSourceimport org.springframework.beans.factory.annotation.{Autowired, Qualifier}import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilderimport org.springframework.boot.context.properties.ConfigurationPropertiesimport org.springframework.boot.orm.jpa.EntityManagerFactoryBuilderimport org.springframework.context.annotation.{Bean, Configuration, PropertySource}import org.springframework.core.env.Environmentimport org.springframework.data.jpa.repository.config.EnableJpaRepositoriesimport org.springframework.orm.jpa.{JpaTransactionManager, LocalContainerEntityManagerFactoryBean}import org.springframework.transaction.PlatformTransactionManager/**  * JPA 数据源配置  */@Configuration@PropertySource(value = Array("classpath:/bootstrap-report.yml"), factory = classOf[YamlPropertyLoaderFactory])@EnableJpaRepositories(  entityManagerFactoryRef = "reportEntityManager",  transactionManagerRef = "reportTransactionManager",  basePackages = Array("com.report.dao"))class ReportDBConfig {  @Autowired  private var env: Environment = _  @Bean  @ConfigurationProperties(prefix = "spring.datasource.report")  def reportDataSource(): DataSource = DataSourceBuilder.create.build  @Bean(name = Array("reportEntityManager"))  def reportEntityManagerFactory(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean = {    val entityManager = builder      .dataSource(reportDataSource())      .packages("com.report.model") //设置JPA实体包路径      .persistenceUnit("reportPU")      .build    entityManager.setJpaProperties(additionalProperties())    entityManager  }  @Bean(name = Array("reportTransactionManager"))  def reportTransactionManager(@Qualifier("reportEntityManager")                               entityManagerFactory: EntityManagerFactory): PlatformTransactionManager = {    new JpaTransactionManager(entityManagerFactory)  }  /**    * 获取JPA配置    *    * @return    */  def additionalProperties(): Properties = {    val properties = new Properties();    properties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.report.hibernate.ddl-auto"))    properties.setProperty("hibernate.show_sql", env.getProperty("spring.jpa.report.show-sql"))    properties.setProperty("hibernate.dialect", env.getProperty("spring.jpa.report.database-platform"))    properties  }}

源码解读

实现该功能涉及两个地方:

1、@PropertySource注解:用于声明和配置自定义配置类需要加载的配置文件信息,源码及属性解释如下:

package org.springframework.context.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Repeatable;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import org.springframework.core.io.support.PropertySourceFactory;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Repeatable(PropertySources.class)public @interface PropertySource {	// 用于声明属性源名称	String name() default "";	// 声明属性文件位置	String[] value();	// 是否忽略未找到的资源	boolean ignoreResourceNotFound() default false;	// 声明配置文件的编码	String encoding() default "";	// 声明解析配置文件的类	Class
factory() default PropertySourceFactory.class;}

2、spring boot配置文件解析类:

在@PropertySource注解的定义中,属性factory主要用来声明解析配置文件的类,这个类必须是PropertySourceFactory接口的实现,在我们自定义了yaml文件加载类之后,它的实现关系如下:

输入图片说明

从以上类图可以发现,它的实现类主要有2个:

  • DefaultPropertySourceFactory:默认的配置文件解析类,主要用于解析properties配置文件
  • YamlPropertyLoaderFactory:自定义的yaml资源解析类,主要用于解析yaml配置文件,使用时需要在PropertySource注解的factory属性上声明

这两个类将配置文件解析后,会将属性信息存入Spring的Environment对象中,以供我们通过@Value注解等方式使用。

因此,我们如果遇到spring boot不能加载并解析自定义配置的时候,可以试试自定义配置文件解析类解决。

参考链接

Properties转YAML idea插件——生产力保证:

转载于:https://my.oschina.net/xiaominmin/blog/1795336

你可能感兴趣的文章
ESXi ftpd安装
查看>>
js去掉空格和
查看>>
PSU更新之后是否更改数据库版本号呢
查看>>
一次应对PowerShell+WMI挖矿***的记录
查看>>
第一天 echo test (()) [[]]
查看>>
OSN2500
查看>>
分享一个NHibernate的博客链接
查看>>
Web开发中8个基础&&常见功能
查看>>
docker之快速部署gogs git
查看>>
jquery返回顶部效果
查看>>
tomcat下如何才能运行shtml文件?
查看>>
我的友情链接
查看>>
将gitee远程仓库抓取(克隆)到本地仓库
查看>>
模糊搜索cell效果
查看>>
Swift项目中不能定义OC类继承Swift类
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
设计模式-观察者模式(发布订阅模式)
查看>>
CTO应该知道的事
查看>>
js清理cookie
查看>>