亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何讓@EnableConfigurationProperties的值注入到@Value中

 更新時(shí)間:2025年06月07日 10:15:28   作者:Boom_Man  
這篇文章主要介紹了如何讓@EnableConfigurationProperties的值注入到@Value中的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

需求背景

定義了一個(gè)@ConfigurationProperties的配置類,然后在其中定義了一些定時(shí)任務(wù)的配置,如cron表達(dá)式,因?yàn)轫?xiàng)目會(huì)有默認(rèn)配置,遂配置中有默認(rèn)值

大體如下:

@Data
@Validated
@ConfigurationProperties(value = "task")
public class TaskConfigProperties {
    /**
     * 任務(wù)A在每天的0點(diǎn)5分0秒進(jìn)行執(zhí)行
     */
     @NotBlank
    private String taskA = "0 5 0 * * ? ";

}

定時(shí)任務(wù)配置:

    @Scheduled(cron = "${task.task-a}")
    public void finalCaseReportGenerate(){
        log.info("taskA定時(shí)任務(wù)開始執(zhí)行");
        //具體的任務(wù)
        log.info("taskA定時(shí)任務(wù)完成執(zhí)行");
    }

但是如上直接使用是有問題的${task.taskA}是沒有值的,必須要在外部化配置中再寫一遍,這樣我們相當(dāng)于默認(rèn)值就沒有用了,這怎么行呢,我們來搞定他。

探究其原理

@ConfigurationProperties、@ValueSpringEl 他們之間的關(guān)系和區(qū)別及我認(rèn)為的正確使用方式。

首先@ConfigurationProperties 是Spring Boot引入的,遂查詢官方文檔的講解

Spring Boot -> Externalized Configuration

我們發(fā)現(xiàn)外部化配置中沒有值的話,報(bào)錯(cuò)是在org.springframework.util.PropertyPlaceholderHelper#parseStringValue

其中org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver是解析的關(guān)鍵

我們只要把默認(rèn)值裝載到系統(tǒng)中,讓org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver#resolvePlaceholder可以解析到就可以了

遂我們可以把值裝載到Environment中

/**
 * @author wangqimeng
 * @date 2020/3/4 0:04
 */
@Data
@Slf4j
@Validated
@ConfigurationProperties(prefix = "task")
public class TaskConfigProperties implements InitializingBean , EnvironmentPostProcessor {

    /**
     * 任務(wù)A在每天的0點(diǎn)5分0秒進(jìn)行執(zhí)行
     */
    @NotBlank
    private String taskA = "0 5 0 * * ? ";

    @Value("${task.task-a}")
    public String taskAValue;

    @Autowired
    private Environment environment;

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("taskAValue:{}",taskAValue);
    }

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        log.info("TaskConfigProperties-> postProcessEnvironment 開始執(zhí)行");
        //取到當(dāng)前配置類上的信息
        MutablePropertySources propertySources = environment.getPropertySources();
        Properties properties = new Properties();
        if (taskA != null) {
            properties.put("task.task-a", this.taskA);
        }
        PropertySource propertySource = new PropertiesPropertySource("task", properties);
        //即優(yōu)先級(jí)低
        propertySources.addLast(propertySource);
    }
}

需要在META-INF -> spring.factories中配置

org.springframework.boot.env.EnvironmentPostProcessor=\
cn.boommanpro.config.TaskConfigProperties

所以addLast是優(yōu)先級(jí)最低的,讓我們新加入的配置優(yōu)先級(jí)最低。

以上就簡單的完成了我們的需求。

最終實(shí)現(xiàn)

配置類中的有默認(rèn)值的不需要在External Configuration中再度配置

通過一個(gè)注解@EnableBindEnvironmentProperties,綁定含有@ConfigurationPropertiesClass的默認(rèn)值到Environment

  • @EnableBindEnvironmentProperties
/**
 * @author wangqimeng
 * @date 2020/3/4 1:21
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableBindEnvironmentProperties {


    Class<?>[] value() default {};
}
  • @EnableBindEnvironmentPropertiesRegister
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;

/**
 * @author wangqimeng
 * @date 2020/3/4 15:11
 */
@Slf4j
public class EnableBindEnvironmentPropertiesRegister implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        MutablePropertySources propertySources = environment.getPropertySources();
        EnableBindEnvironmentProperties annotation = application.getMainApplicationClass().getAnnotation(EnableBindEnvironmentProperties.class);
        Arrays.stream(annotation.value())
                .forEach(aClass -> registerToEnvironment(propertySources, aClass));
    }

    public void registerToEnvironment(MutablePropertySources propertySources, Class<?> clazz) {
        ConfigurationProperties annotation = clazz.getAnnotation(ConfigurationProperties.class);
        if (annotation == null) {
            return;
        }
        String prefix = annotation.prefix();
        String name = String.format("%s-%s", prefix, clazz.getName());
        try {
            Properties properties = toProperties(prefix, clazz.newInstance());
            PropertySource propertySource = new PropertiesPropertySource(name, properties);
            propertySources.addLast(propertySource);
        } catch (Exception e) {
            log.error("Exception:", e);
            throw new RuntimeException();
        }

    }

    public Properties toProperties(String prefix, Object o) throws Exception {
        Properties properties = new Properties();
        Map<String, Object> map = objectToMap(o);
        map.forEach((s, o1) -> {
            properties.put(String.format("%s.%s", prefix, camelToUnderline(s)), o1);
        });

        return properties;
    }

    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append("-");
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static Map<String, Object> objectToMap(Object obj) throws Exception {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>(10);
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter != null ? getter.invoke(obj) : null;
            if (value == null) {
                continue;
            }
            map.put(key, value);
        }

        return map;
    }
}

配置到META-INF/spring.factories

# Application Listeners
org.springframework.boot.env.EnvironmentPostProcessor=\
cn.boommanpro.annotation.EnableBindEnvironmentPropertiesRegister

總結(jié)

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

相關(guān)文章

  • 快速搭建springboot項(xiàng)目(新手入門)

    快速搭建springboot項(xiàng)目(新手入門)

    本文主要介紹了快速搭建springboot項(xiàng)目(新手入門),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 美化java代碼,從合理注釋開始

    美化java代碼,從合理注釋開始

    在Java的編寫過程中我們需要對(duì)一些程序進(jìn)行注釋,除了自己方便閱讀,更為別人更好理解自己的程序,可以是編程思路或者是程序的作用,總而言之就是方便自己他人更好的閱讀。下面我們來一起學(xué)習(xí)一下吧
    2019-06-06
  • 使用Java反射機(jī)制提高SpringBoot的代碼質(zhì)量和可維護(hù)性

    使用Java反射機(jī)制提高SpringBoot的代碼質(zhì)量和可維護(hù)性

    保持好的代碼質(zhì)量和遵守編碼標(biāo)準(zhǔn)是開發(fā)可維護(hù)和健壯軟件的重要方面,在本文中,我們將探討如何使用 Java 反射來提高 Spring Boot 應(yīng)用程序的代碼質(zhì)量和可維護(hù)性,需要的朋友可以參考下
    2023-10-10
  • Java實(shí)現(xiàn)SM3withSM2簽名和驗(yàn)證的基本示例

    Java實(shí)現(xiàn)SM3withSM2簽名和驗(yàn)證的基本示例

    這篇文章主要介紹了Java實(shí)現(xiàn)SM3withSM2簽名和驗(yàn)證的基本示例,SM3withSM2是一種在Java中使用的密碼學(xué)算法組合,結(jié)合了橢圓曲線公鑰密碼算法SM2和密碼哈希算法SM3,它主要用于數(shù)字簽名和數(shù)據(jù)完整性校驗(yàn),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • 淺析對(duì)Java關(guān)鍵字final和static的理解

    淺析對(duì)Java關(guān)鍵字final和static的理解

    本文主要給大家談?wù)勑【帉?duì)java關(guān)鍵字final和static的理解,本文給大家介紹的較詳細(xì),需要的朋友參考參考下
    2017-04-04
  • 深入講解Java的對(duì)象頭與對(duì)象組成

    深入講解Java的對(duì)象頭與對(duì)象組成

    由于Java面向?qū)ο蟮乃枷?在JVM中需要大量存儲(chǔ)對(duì)象,存儲(chǔ)時(shí)為了實(shí)現(xiàn)一些額外的功能,需要在對(duì)象中添加一些標(biāo)記字段用于增強(qiáng)對(duì)象功能,這些標(biāo)記字段組成了對(duì)象頭,下面這篇文章主要給大家介紹了關(guān)于Java對(duì)象頭與對(duì)象組成的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Java如何取掉json數(shù)據(jù)中值為null的屬性字段

    Java如何取掉json數(shù)據(jù)中值為null的屬性字段

    這篇文章主要介紹了Java如何取掉json數(shù)據(jù)中值為null的屬性字段,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • MyBatis處理CLOB/BLOB類型數(shù)據(jù)以及解決讀取問題

    MyBatis處理CLOB/BLOB類型數(shù)據(jù)以及解決讀取問題

    這篇文章主要介紹了MyBatis處理CLOB/BLOB類型數(shù)據(jù)以及解決讀取問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • SpringCloudAlibaba分布式組件詳解

    SpringCloudAlibaba分布式組件詳解

    這篇文章主要介紹了簡單了解Spring Cloud Alibaba分布式組件相關(guān)知識(shí),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Java Lambda表達(dá)式和函數(shù)式接口實(shí)例分析

    Java Lambda表達(dá)式和函數(shù)式接口實(shí)例分析

    這篇文章主要介紹了Java Lambda表達(dá)式和函數(shù)式接口,結(jié)合實(shí)例形式分析了Java8 Lambda表達(dá)式和函數(shù)式接口相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-09-09

最新評(píng)論