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

SpringBoot中@ConfigurationProperties注解的使用與源碼詳解

 更新時間:2023年11月18日 09:42:21   作者:morris131  
這篇文章主要介紹了SpringBoot中@ConfigurationProperties注解的使用與源碼詳解,@ConfigurationProperties注解用于自動配置綁定,可以將application.properties配置中的值注入到bean對象上,需要的朋友可以參考下

前言

相信大家肯定了解@Value注解,它可以通過一個配置文件中的屬性名與對象的屬性進(jìn)行綁定。

@ConfigurationProperties注解的作用其實就類似于使用多個@Value注解同時綁定一個對象的多個屬性,@ConfigurationProperties注解用于自動配置綁定,可以將application.properties配置中的值(準(zhǔn)確來說是Environment中的屬性值)注入到bean對象上,該注解的使用必須先將對象注入到IOC容器中才有配置自動綁定的功能。

@ConfigurationProperties注解的使用

先來看下@ConfigurationProperties的源碼:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface ConfigurationProperties {
	// 匹配的前綴
    @AliasFor("prefix")
    String value() default "";

	// 同上
    @AliasFor("value")
    String prefix() default "";

	// 忽略屬性類型不匹配的字段
    boolean ignoreInvalidFields() default false;

	// 忽略類中未知的屬性,ignoreUnknownFields=false后當(dāng)出現(xiàn)未知字段時會出現(xiàn)異常
    boolean ignoreUnknownFields() default true;
}

注解使用在類上:

package com.morris.spring.boot.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {

	private String username;

	private String password;

	private String driverClass;

	private String connectionUrl;

}

配置文件中的屬性名稱需要與實體類的屬性保持一致,不然值會綁定不上,多個單詞可以使用橫杠進(jìn)行分割,SpringBoot會將橫杠命名轉(zhuǎn)駝峰命名。

注解使用方法上:

package com.morris.spring.boot.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
public class FlowRuleConfig {

	@Bean
	@ConfigurationProperties("flow.config")
	public RuleProperties ruleProperties() {
		return new RuleProperties();
	}

	@Data
	public static class RuleProperties {
		private Map<String, Integer> rules;
	}
}

@ConfigurationProperties注解的原理

在SpringBoot的spring.factories文件注入了org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration。

ConfigurationPropertiesAutoConfiguration

ConfigurationPropertiesAutoConfiguration上面加了@EnableConfigurationProperties注解。

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
public class ConfigurationPropertiesAutoConfiguration {

}

@EnableConfigurationProperties

@EnableConfigurationProperties注解導(dǎo)入了EnableConfigurationPropertiesRegistrar類。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableConfigurationPropertiesRegistrar.class)
public @interface EnableConfigurationProperties {

	/**
	 * The bean name of the configuration properties validator.
	 * @since 2.2.0
	 */
	String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";

	/**
	 * Convenient way to quickly register
	 * {@link ConfigurationProperties @ConfigurationProperties} annotated beans with
	 * Spring. Standard Spring Beans will also be scanned regardless of this value.
	 * @return {@code @ConfigurationProperties} annotated beans to register
	 */
	Class<?>[] value() default {};

}

EnableConfigurationPropertiesRegistrar

EnableConfigurationPropertiesRegistrar實現(xiàn)了ImportBeanDefinitionRegistrar接口,主要用于向Spring容器中注入Bean。

主要注入了以下Bean:

  • ConfigurationPropertiesBindingPostProcessor
  • BoundConfigurationProperties
  • MethodValidationExcludeFilter
  • ConfigurationPropertiesBinder

org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar#registerBeanDefinitions

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
	// 注入ConfigurationPropertiesBindingPostProcessor
	// 注入BoundConfigurationProperties
	registerInfrastructureBeans(registry);
	// 注入MethodValidationExcludeFilter
	registerMethodValidationExcludeFilter(registry);

	// 注入@EnableConfigurationProperties注解指定的ConfigurationProperties
	// 例如org.springframework.boot.autoconfigure.web.ServerProperties
	ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
	getTypes(metadata).forEach(beanRegistrar::register);
}

ConfigurationPropertiesBindingPostProcessor

ConfigurationPropertiesBindingPostProcessor實現(xiàn)了BeanPostProcessor接口,其postProcessBeforeInitialization()方法會在Bean實例化后執(zhí)行,在這里完成了配置文件的屬性與對象的屬性的綁定。

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
	return bean;
}

private void bind(ConfigurationPropertiesBean bean) {
	if (bean == null || hasBoundValueObject(bean.getName())) {
		return;
	}
	Assert.state(bean.getBindMethod() == BindMethod.JAVA_BEAN, "Cannot bind @ConfigurationProperties for bean '"
				 + bean.getName() + "'. Ensure that @ConstructorBinding has not been applied to regular bean");
	try {
		// 主要是通過ConfigurationPropertiesBinder來完成配置文件的屬性與對象的屬性的綁定
		// 最終會調(diào)用Binder這個類來完成綁定
		this.binder.bind(bean);
	}
	catch (Exception ex) {
		throw new ConfigurationPropertiesBindException(bean, ex);
	}
}

ConfigurationPropertiesBinder

ConfigurationPropertiesBinder主要負(fù)責(zé)構(gòu)建Binder并進(jìn)行緩存,SpringBoot啟動過程中已經(jīng)將配置文件的屬性值存到Environment中的PropertySources中了,所以Binder只要從Environment中獲取即可。

ConfigurationPropertiesBinder(ApplicationContext applicationContext) {
	this.applicationContext = applicationContext;
	this.propertySources = new PropertySourcesDeducer(applicationContext).getPropertySources();
	this.configurationPropertiesValidator = getConfigurationPropertiesValidator(applicationContext);
	this.jsr303Present = ConfigurationPropertiesJsr303Validator.isJsr303Present(applicationContext);
}

BindResult<?> bind(ConfigurationPropertiesBean propertiesBean) {
	Bindable<?> target = propertiesBean.asBindTarget();
	ConfigurationProperties annotation = propertiesBean.getAnnotation();
	BindHandler bindHandler = getBindHandler(target, annotation);
	return getBinder().bind(annotation.prefix(), target, bindHandler);
}

private Binder getBinder() {
	if (this.binder == null) {
		this.binder = new Binder(getConfigurationPropertySources(), getPropertySourcesPlaceholdersResolver(),
								 getConversionServices(), getPropertyEditorInitializer(), null,
								 ConfigurationPropertiesBindConstructorProvider.INSTANCE);
	}
	return this.binder;
}

如何動態(tài)刷新@ConfigurationProperties

如果配置中心配置更新了,遇到了@ConfigurationProperties標(biāo)注的配置bean,那么bean的屬性就不會自動更新了,那么實現(xiàn)動態(tài)更新@ConfigurationProperties標(biāo)注的bean的屬性呢?

如果使用的Nacos注冊中心,可以監(jiān)聽NacosConfigReceivedEvent事件后使用SpringBoot提供的Binder進(jìn)行bean的屬性的更新:

DatabaseProperties databaseProperties = applicationContext.getBean(DatabaseProperties.class);
System.out.println(databaseProperties);

// test refresh @ConfigurationProperties
// 這里使用app.properties模擬
ClassPathResource classPathResource = new ClassPathResource("app.properties");
ResourcePropertySource resourcePropertySource = new ResourcePropertySource(classPathResource);
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(resourcePropertySource);
Binder binder = new Binder(configurationPropertySource);
Bindable<DatabaseProperties> bindable = Bindable.ofInstance(databaseProperties);
binder.bind("database", bindable);
System.out.println(databaseProperties);

當(dāng)前最簡單的辦法就是在bean上面加上@RefreshScope注解就能實現(xiàn)自動刷新屬性值了。

到此這篇關(guān)于SpringBoot中@ConfigurationProperties注解的使用與源碼詳解的文章就介紹到這了,更多相關(guān)@ConfigurationProperties注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA卡在”正在解析Maven依賴項“的解決方法

    IDEA卡在”正在解析Maven依賴項“的解決方法

    在創(chuàng)建新的SpringBoot項目時,始終卡在"正在解析Maven依賴項…",本文小編給大家介紹了幾種相關(guān)的解決方案,具有一定的參考價值,需要的朋友可以參考下
    2023-11-11
  • Spring中校驗器(Validator)的深入講解

    Spring中校驗器(Validator)的深入講解

    Spring校驗器,參數(shù)校驗從此簡單。下面這篇文章主要給大家介紹了關(guān)于Spring中校驗器(Validator)的相關(guān)資料,文中通過示例代碼介紹非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • Java報錯Non-terminating?decimal?expansion解決分析

    Java報錯Non-terminating?decimal?expansion解決分析

    這篇文章主要為大家介紹了Java報錯Non-terminating?decimal?expansion解決方案及原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java常用鎖synchronized和ReentrantLock的區(qū)別

    Java常用鎖synchronized和ReentrantLock的區(qū)別

    這篇文章主要介紹了Java常用鎖synchronized和ReentrantLock的區(qū)別,二者的功效都是相同的,但又有很多不同點,下面我們就進(jìn)入文章了解具體的相關(guān)內(nèi)容吧。需要的小伙伴也可以參考一下
    2022-05-05
  • SpringIoC與SpringDI詳解

    SpringIoC與SpringDI詳解

    本文介紹了Spring框架中的IoC(控制反轉(zhuǎn))和DI(依賴注入)概念,以及如何在Spring中使用這些概念來管理對象和依賴關(guān)系,感興趣的朋友一起看看吧
    2025-03-03
  • 教你怎么使用Optional處理null

    教你怎么使用Optional處理null

    今天教各位小伙伴怎么使用Optional處理null,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有很大的幫助,需要的朋友可以參考下
    2021-05-05
  • Java簡單數(shù)據(jù)加密方法DES實現(xiàn)過程解析

    Java簡單數(shù)據(jù)加密方法DES實現(xiàn)過程解析

    這篇文章主要介紹了Java簡單數(shù)據(jù)加密方法DES實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Jmeter后置處理器實現(xiàn)過程及方法應(yīng)用

    Jmeter后置處理器實現(xiàn)過程及方法應(yīng)用

    這篇文章主要介紹了Jmeter后置處理器實現(xiàn)過程及方法應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • SpringSecurity實現(xiàn)動態(tài)權(quán)限校驗的過程

    SpringSecurity實現(xiàn)動態(tài)權(quán)限校驗的過程

    Spring Security過濾器鏈中,AuthorizationFilter的authorizationManager是我們要找的組件,該組件的check方法已被棄用,推薦使用authorize方法,最終通過接口路徑和權(quán)限進(jìn)行校驗,本文給大家介紹SpringSecurity實現(xiàn)動態(tài)權(quán)限校驗的相關(guān)知識,感興趣的朋友一起看看吧
    2025-02-02
  • RabbitMQ消息丟失解決方案

    RabbitMQ消息丟失解決方案

    把這篇文章主要為大家介紹了如何保證RabbitMQ消息不丟失的解決方發(fā),分從從丟失的三種情況給大家介紹不同的解決方案,感興趣的小伙伴可以參考閱讀本文
    2023-07-07

最新評論