⽬录
⾃定义加载yml,附源码解读
解决⽅法源码解读
如何引⼊多个yml⽅法
⽅案⼀:⽆前缀,使⽤@Value注解⽅案⼆:有前缀,⽆需@Value注解
⾃定义加载yml,附源码解读
昨天在对公司的微服务配置⽂件标准化的过程中,发现将原来的properties⽂件转为yml⽂件之后,微服务module中标记有@Configuration的配置类都不能正常⼯作了,究其原因,是由于@PropertySource属性默认只⽤于标记并告诉spring boot加载properties类型的⽂件spring boot 2.0.0.RELEASE版的⽂档解释如下:
24.6.4 YAML Shortcomings
*************************************************************,inthecasethatyouneedtoloadvaluesthatway,youneedtouse a properties file.这段话的意思是说:
24.6.4 YAML 缺点
YAML ⽂件不能⽤ @PropertySource 注解来标记加载。因此,在需要加载值的场景,你需要使⽤属性⽂件。
解决⽅法
解决这个问题并不难,我们只需要⾃定义⼀个yaml⽂件加载类,并在@PropertySource注解的factory属性中声明就可以。scala版实现代码如下,springboot版本为2.0.0.RELEASE:1、⾃定义yaml⽂件资源加载类
import org.springframework.boot.env.YamlPropertySourceLoaderimport org.springframework.core.env.PropertySource
import 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.DataSource
import 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.EntityManagerFactoryBuilder
import org.springframework.context.annotation.{Bean, Configuration, PropertySource}import org.springframework.core.env.Environment
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import 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\ properties.setProperty(\"hibernate.show_sql\
properties.setProperty(\"hibernate.dialect\ 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 extends PropertySourceFactory> 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插件——⽣产⼒保证:
如何引⼊多个yml⽅法
SpringBoot默认加载的是application.yml⽂件,所以想要引⼊其他配置的yml⽂件,就要在application.yml中激活该⽂件定义⼀个application-resources.yml⽂件(注意:必须以application-开头)
application.yml中:
spring: profiles:
active: resources
以上操作,xml⾃定义⽂件加载完成,接下来进⾏注⼊。application-resources.yml配置⽂件代码:
user:
filepath: 12346 uname: \"13\"admin:
aname: 26
⽅案⼀:⽆前缀,使⽤@Value注解
@Component
//@ConfigurationProperties(prefix = \"user\")public class User {
@Value(\"${user.filepath}\") private String filepath; @Value(\"${user.uname}\") private String uname;
public String getFilepath() { return filepath; }
public void setFilepath(String filepath) { this.filepath = filepath; }
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
@Override
public String toString() { return \"User{\" +
\"filepath='\" + filepath + '\\'' + \ '}'; }}
⽅案⼆:有前缀,⽆需@Value注解
@Component
@ConfigurationProperties(prefix = \"user\")public class User {
//@Value(\"${user.filepath}\") private String filepath;
//@Value(\"${user.uname}\") private String uname;
public String getFilepath() { return filepath; }
public void setFilepath(String filepath) { this.filepath = filepath; }
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
@Override
public String toString() { return \"User{\" +
\"filepath='\" + filepath + '\\'' + \ '}'; }}
测试类:
package com.sun123.springboot;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class UTest { @Autowired User user; @Test
public void test01(){
System.out.println(user); }}
测试结果:
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- xiaozhentang.com 版权所有 湘ICP备2023022495号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务