您好,欢迎来到小侦探旅游网。
搜索
您的当前位置:首页SpringBoot自定义加载yml实现方式,附源码解读

SpringBoot自定义加载yml实现方式,附源码解读

来源:小侦探旅游网
SpringBoot⾃定义加载yml实现⽅式,附源码解读

⽬录

⾃定义加载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 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

本站由北京市万商天勤律师事务所王兴未律师提供法律服务