欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot自定義加載yml實(shí)現(xiàn)方式,附源碼解讀

 更新時(shí)間:2022年03月24日 09:47:55   作者:九州暮云  
這篇文章主要介紹了SpringBoot自定義加載yml實(shí)現(xiàn)方式附源碼解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

自定義加載yml,附源碼解讀

昨天在對(duì)公司的微服務(wù)配置文件標(biāo)準(zhǔn)化的過程中,發(fā)現(xiàn)將原來的properties文件轉(zhuǎn)為yml文件之后,微服務(wù)module中標(biāo)記有@Configuration的配置類都不能正常工作了,究其原因,是由于@PropertySource屬性默認(rèn)只用于標(biāo)記并告訴spring boot加載properties類型的文件

spring boot 2.0.0.RELEASE版的文檔解釋如下:

24.6.4 YAML Shortcomings

YAML 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 缺點(diǎn)

YAML 文件不能用 @PropertySource 注解來標(biāo)記加載。因此,在需要加載值的場(chǎng)景,你需要使用屬性文件。

解決方法

解決這個(gè)問題并不難,我們只需要自定義一個(gè)yaml文件加載類,并在@PropertySource注解的factory屬性中聲明就可以。scala版實(shí)現(xiàn)代碼如下,spring boot版本為2.0.0.RELEASE:

1、自定義yaml文件資源加載類 

import org.springframework.boot.env.YamlPropertySourceLoader
import 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)
? }
}

這個(gè)類繼承自DefaultPropertySourceFactory類,并重寫了createPropertySource方法。

2、引入@PropertySource注解并使用

import com.core.conf.YamlPropertyLoaderFactory
import javax.persistence.EntityManagerFactory
import javax.sql.DataSource
import org.springframework.beans.factory.annotation.{Autowired, Qualifier}
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder
import org.springframework.boot.context.properties.ConfigurationProperties
import 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 數(shù)據(jù)源配置
? */
@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") //設(shè)置JPA實(shí)體包路徑
? ? ? .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
? }
}

源碼解讀

實(shí)現(xiàn)該功能涉及兩個(gè)地方:

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主要用來聲明解析配置文件的類,這個(gè)類必須是PropertySourceFactory接口的實(shí)現(xiàn),在我們自定義了yaml文件加載類之后,它的實(shí)現(xiàn)關(guān)系如下:

從以上類圖可以發(fā)現(xiàn),它的實(shí)現(xiàn)類主要有2個(gè):

  • DefaultPropertySourceFactory:默認(rèn)的配置文件解析類,主要用于解析properties配置文件
  • YamlPropertyLoaderFactory:自定義的yaml資源解析類,主要用于解析yaml配置文件,使用時(shí)需要在PropertySource注解的factory屬性上聲明

這兩個(gè)類將配置文件解析后,會(huì)將屬性信息存入Spring的Environment對(duì)象中,以供我們通過@Value注解等方式使用。

因此,我們?nèi)绻龅絪pring boot不能加載并解析自定義配置的時(shí)候,可以試試自定義配置文件解析類解決。

參考鏈接

YAML Shortcomings

Exposing YAML as Properties in the Spring Environment

ConfigurationProperties loading list from YML:base on kotlin

Properties轉(zhuǎn)YAML idea插件——生產(chǎn)力保證:Properties to YAML Converter

如何引入多個(gè)yml方法

SpringBoot默認(rèn)加載的是application.yml文件,所以想要引入其他配置的yml文件,就要在application.yml中激活該文件

定義一個(gè)application-resources.yml文件(注意:必須以application-開頭)

application.yml中:

spring:?
?profiles:
? ?active: resources

以上操作,xml自定義文件加載完成,接下來進(jìn)行注入。

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 + '\'' +
? ? ? ? ? ? ? ?", uname='" + uname + '\'' +
? ? ? ? ? ? ? ?'}';
? ?}
}

方案二:有前綴,無需@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 + '\'' +
? ? ? ? ? ? ? ?", uname='" + uname + '\'' +
? ? ? ? ? ? ? ?'}';
? ?}
}

測(cè)試類:

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)
@SpringBootTest
public class UTest {
? ?@Autowired
? ?User user;
? ?@Test
? ?public void test01(){
? ? ? ?System.out.println(user);
? ?}
}

測(cè)試結(jié)果:

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 再也不用怕! 讓你徹底搞明白Java內(nèi)存分布

    再也不用怕! 讓你徹底搞明白Java內(nèi)存分布

    做Java的大都沒有c++ 的那種分配內(nèi)存的煩惱,因?yàn)镴ava 幫我們管理內(nèi)存,但是這并不代表我們不需要了解Java的內(nèi)存結(jié)構(gòu),因?yàn)榫€上經(jīng)常出現(xiàn)內(nèi)存的問題,今天聊一下內(nèi)存的問題,需要的朋友可以參考下
    2021-06-06
  • java線程池使用后到底要關(guān)閉嗎

    java線程池使用后到底要關(guān)閉嗎

    這篇文章主要給大家介紹了關(guān)于java線程池使用后到底要不要關(guān)閉的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • Spring Boot攔截器和過濾器實(shí)例解析

    Spring Boot攔截器和過濾器實(shí)例解析

    這篇文章主要介紹了Spring Boot攔截器和過濾器實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 一文徹底搞懂Java和JDK的版本命名問題

    一文徹底搞懂Java和JDK的版本命名問題

    今天通過本文給大家分享我對(duì)Java的版本號(hào)以及JDK的命名的了解,通過實(shí)例圖文展示給大家介紹的非常詳細(xì),需要的朋友跟隨小編一起看看吧
    2021-06-06
  • Spring Boot和Hazelcast使用詳解

    Spring Boot和Hazelcast使用詳解

    這篇文章主要介紹了Spring Boot和Hazelcast使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • 硬核 Redis 高頻面試題解析

    硬核 Redis 高頻面試題解析

    Redis 是一個(gè)高性能的key-value數(shù)據(jù)庫。在部分場(chǎng)合可以對(duì)關(guān)系數(shù)據(jù)庫起到很好的補(bǔ)充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端使用很方便
    2021-06-06
  • JAVA讀取二進(jìn)制文件以及畫圖教程

    JAVA讀取二進(jìn)制文件以及畫圖教程

    由于項(xiàng)目需要,需要對(duì)二進(jìn)制文件進(jìn)行讀取,所以這篇文章主要給大家介紹了關(guān)于JAVA讀取二進(jìn)制文件以及畫圖的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java包機(jī)制及javadoc詳解

    Java包機(jī)制及javadoc詳解

    為了更好地組織類,Java提供了包機(jī)制,用于區(qū)別類名的命名空間,一般利用公司域名倒置作為包名,這篇文章主要介紹了Java包機(jī)制以及javadoc,需要的朋友可以參考下
    2022-10-10
  • springboot數(shù)據(jù)庫操作圖文教程

    springboot數(shù)據(jù)庫操作圖文教程

    本文以圖文并茂的形式給大家介紹了springboot數(shù)據(jù)庫操作,感興趣的朋友一起看看吧
    2017-07-07
  • Java中的線程安全集合CopyOnWriteArrayList解析

    Java中的線程安全集合CopyOnWriteArrayList解析

    這篇文章主要介紹了Java中的線程安全CopyOnWriteArrayList解析,CopyOnWriteArrayList是ArrayList的線程安全版本,從他的名字可以推測(cè),CopyOnWriteArrayList是在有寫操作的時(shí)候會(huì)copy一份數(shù)據(jù),然后寫完再設(shè)置成新的數(shù)據(jù),需要的朋友可以參考下
    2023-12-12

最新評(píng)論