最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

@ConfigurationProperties注解原理與實踐方式

 更新時間:2026年06月03日 09:24:47   作者:小大宇  
這段文章詳細介紹了@ConfigurationProperties在SpringBoot中的使用方法,并探討了其源碼實現(xiàn)原理,進而引導讀者自己實現(xiàn)類似功能,涵蓋配置文件解析、Bean生命周期管理等內(nèi)容,同時強調(diào)了通過學習SpringBoot源碼來實現(xiàn)自定義功能的重要性

一、@ConfigurationProperties 基本使用

在 SpringBoot 中,當想需要獲取到配置文件數(shù)據(jù)時,除了可以用 Spring 自帶的 @Value 注解外,SpringBoot 還提供了一種更加方便的方式:@ConfigurationProperties。只要在 Bean 上添加上了這個注解,指定好配置文件的前綴,那么對應的配置文件數(shù)據(jù)就會自動填充到 Bean 中。

比如在application.properties文件中有如下配置文件

config.username=jay.zhou
config.password=3333

那么按照如下注解配置,SpringBoot項目中使用@ConfigurationProperties的Bean,它的username與password就會被自動注入值了。

就像下面展示的那樣

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "config")
public class TestBean{
    private String username;
    private String password;
}

二、@ConfigurationProperties 源碼的探索及啟發(fā)

SpringBoot為什么能夠獲取到它的值呢?如果讓我從無到有設計,我應該怎么設計呢?

首先通過源碼發(fā)現(xiàn),SpringBoot主要幫助我們做了兩件事情。

  • 第一件事情就是獲取到使用@ConfigurationProperties的類。
  • 第二件事就是解析配置文件,并把對應的值設置到我們的Bean中。

按照源碼提供的實現(xiàn)思路,其核心就是對Bean的聲明周期的管理。主要涉及一個叫做 BeanPostProcessor 的接口,可以在Bean初始化的時候,我們做一些文章。

下面的兩個方法,很簡單,大致意思就是,在Spring的Bean初始化之前與之后執(zhí)行。

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

好了,作為程序員,看了半天源碼,扯了半天淡,不如自己實現(xiàn)一個類似的效果來的實在。

三、代碼

第一步,定義自己的注解。這個注解最后實現(xiàn)的功能希望與@ConfigurationProperties 類似。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {
    /**
     * 配置屬性 的前綴
     */
    String prefix();
}

第二步,定義配置測試實體。

用上了我們剛才定義的@Config注解,并指明其prefix屬性的值為 " default "

import lombok.Data;
import org.springframework.stereotype.Component;
@Config(prefix = "default")
@Component
@Data
public class TestDataSource {
    private String username;
    private String password;
    private int maxActiveCount;
}

第三步,編寫我們的自己的配置文件。為了便于操作(實際上其它的我不會解析),使用properties這種文件類型。

我們的目標就是把 " default." 后面的對應的字段,注入到上面的TestDataSource里面。

config.properties

default.username = root
default.password = 3333
default.maxActiveCount = 10
default.maxActiveCount2 = 10

第四步,編寫處理邏輯。

(1)獲取使用了我們自定義注解@Config的類

(2)解析配置文件,并將對應的值使用反射技術,注入到Bean中。

下面是最主要的處理代碼。實現(xiàn)BeanPostProcessor接口的方法,檢查每一個初始化成功的Bean,如果使用了我們的自定義注解,那么就把從配置文件中解析出來的數(shù)據(jù),使用反射技術注入進去。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
@Component
public class ConfigPostProcess implements BeanPostProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigPostProcess.class);
    private static final String FILE_NAME = "config.properties";
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //獲取使用了我們自定義注解@Config的類
        Config configAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), Config.class);
        //如果這個對象使用了此注解
        if (configAnnotation != null) {
            LOGGER.info("當前操作的類:{}", beanName);
            //解析配置文件,并將解析結果放入Map中
            Map<String, String> configProperties = getConfigPropertiesFromFile(configAnnotation);
            //將對應的值,使用反射技術,注入到這個bean中
            bindBeanValue(bean, configProperties);
        }
        return bean;
    }
  ...
}

四、實現(xiàn)效果

SpringBoot很多都是通過注解來實現(xiàn)功能的。只要我們能夠?qū)W習其源碼實現(xiàn)思路,我們也可以做出很多很多類似的功能。盡管我們的代碼健壯性做不到跟大佬一樣,但是在特定業(yè)務場景下,比如對某個特別重要的單例Bean進行操作,或者為某一類特定的接口實現(xiàn),做一些特定的處理,可以考慮這種技術。

另外,對于反射的使用,在SpringBoot框架學習過程中也是一個非常重要的部分。

只有經(jīng)常手敲代碼,才能孰能生巧,切忌紙上談兵。只有切實自己實現(xiàn)了特定功能,回頭查看SpringBoot替我們做的事情,才能做到心中有數(shù),否則被新手程序員問一句 " 為什么要這么配置 " 就啞口無言,實在是很尷尬。

點擊動圖后,效果可以更加清楚哦?。。?/span>

附錄私有方法

   /**
     * 將對應的值,使用反射技術,注入到這個bean中
     */
    private void bindBeanValue(Object bean, Map<String, String> configProperties) {
        if (configProperties.size() > 0) {
            configProperties.forEach((key, value) -> {
                setFieldValueByFieldName(key, bean, value);
            });
        }
    }
    /**
     *  從配置文件中讀取配置好的鍵值對,并放入到Map中
     */
    private Map<String, String> getConfigPropertiesFromFile(Config configAnnotation) {
        //get prefix from annotation
        String prefix = configAnnotation.prefix();
        //read value from resource file
        Properties properties = getClassNameFromResource(FILE_NAME);
        Map<String, String> configProperties = new HashMap<>();
        Set<String> keys = properties.stringPropertyNames();
        List<String> keyList = new ArrayList<>(keys);
        for (String key : keyList) {
            if (key.startsWith(prefix)) {
                //default.password ==> password
                String realKey = key.substring(key.indexOf(prefix) + prefix.length() + 1);
                String value = properties.getProperty(key);
                configProperties.put(realKey, value);
            }
        }
        return configProperties;
    }
    /**
     * 讀取配置文件,返回一個流對象
     */
    private Properties getClassNameFromResource(String fileName) {
        Properties properties = new Properties();
        ClassLoader classLoader = ConfigPostProcess.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream(fileName);
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }
    /**
     * 為指定字段使用反射技術設值(只支持String 與 int 類型)
     */
    private void setFieldValueByFieldName(String fieldName, Object object, String value) {
        try {
            Class c = object.getClass();
            if (checkFieldExists(fieldName, c)) {
                Field f = c.getDeclaredField(fieldName);
                f.setAccessible(true);
                //如果不是String,那么就是int。其它類型不支持
                if(f.getType().equals(String.class)){
                    f.set(object, value);
                }else{
                    int number = Integer.valueOf(value);
                    f.set(object, number);
                }
            }
        } catch (Exception e) {
            LOGGER.error("設置" + fieldName + "出錯");
        }
    }
    /**
     * 檢查這個Bean是否有配置文件中配置的字段
     * 沒有就不設置了
     */
    private boolean checkFieldExists(String fieldName, Class c) {
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().equals(fieldName)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

總結

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

相關文章

  • java Swing實現(xiàn)選項卡功能(JTabbedPane)實例代碼

    java Swing實現(xiàn)選項卡功能(JTabbedPane)實例代碼

    這篇文章主要介紹了java Swing實現(xiàn)選項卡功能(JTabbedPane)實例代碼的相關資料,學習java 基礎的朋友可以參考下這個簡單示例,需要的朋友可以參考下
    2016-11-11
  • Java注解Annotaton詳解

    Java注解Annotaton詳解

    Java 注解(Annotation)又稱 Java 標注,是 JDK5.0 引入的一種注釋機制,文中給大家介紹了三種基本的Annotaton,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2022-05-05
  • Springboot如何優(yōu)雅的關閉應用

    Springboot如何優(yōu)雅的關閉應用

    這篇文章主要介紹了Springboot如何優(yōu)雅的關閉應用問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Spring Cloud微服務之間調(diào)用Dubbo的詳細過程

    Spring Cloud微服務之間調(diào)用Dubbo的詳細過程

    SpringCloudAlibabaDubbo是阿里巴巴開源的Dubbo與SpringCloud的深度集成方案,本文介紹Spring Cloud微服務之間調(diào)用Dubbo的詳細過程,感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • java實現(xiàn)微信搶紅包算法

    java實現(xiàn)微信搶紅包算法

    這篇文章主要為大家詳細介紹了java實現(xiàn)微信搶紅包算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • 解決idea services窗口不見的一種特殊情況(小白采坑系列)

    解決idea services窗口不見的一種特殊情況(小白采坑系列)

    這篇文章主要介紹了解決idea services窗口不見的一種特殊情況(小白采坑系列),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解

    SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解

    這篇文章主要介紹了SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • IDEA設置背景為自定義照片的操作方法

    IDEA設置背景為自定義照片的操作方法

    這篇文章主要介紹了IDEA設置背景為自定義照片,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • 用Java集合中的Collections.sort方法如何對list排序(兩種方法)

    用Java集合中的Collections.sort方法如何對list排序(兩種方法)

    本文通過兩種方法給大家介紹java集合中的Collections.sort方法對list排序,第一種方式是list中的對象實現(xiàn)Comparable接口,第二種方法是根據(jù)Collections.sort重載方法實現(xiàn),對collections.sort方法感興趣的朋友一起學習吧
    2015-10-10
  • java基礎學習筆記之泛型

    java基礎學習筆記之泛型

    所謂泛型,就是變量類型的參數(shù)化。泛型是JDK1.5中一個最重要的特征。通過引入泛型,我們將獲得編譯時類型的安全和運行時更小的拋出ClassCastException的可能。在JDK1.5中,你可以聲明一個集合將接收/返回的對象的類型。
    2016-02-02

最新評論

榆树市| 永城市| 仲巴县| 武定县| 连南| 江油市| 沾益县| 高邑县| 滦南县| 阿克| 达孜县| 铅山县| 连州市| 高阳县| 新疆| 马尔康县| 连城县| 静海县| 酒泉市| 扶余县| 祁东县| 嘉义县| 蚌埠市| 班戈县| 岗巴县| 文登市| 平乐县| 永春县| 东莞市| 佳木斯市| 得荣县| 滨州市| 福鼎市| 汶上县| 陵水| 北海市| 正宁县| 巴林右旗| 株洲县| 泗洪县| 将乐县|