您好,登錄后才能下訂單哦!
本篇內容主要講解“Value注解支持對象類型ConfigurationProperties功能問題怎么解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Value注解支持對象類型ConfigurationProperties功能問題怎么解決”吧!
(不希望配置類注冊為Bean 或 不希望聲明@ConfigurationProperties)
假設某一個jar包內封裝了DataSourceProperties
@Configuration @ConfigurationProperties( prefix = "my.datasource" ) @Data public class DataSourceProperties { private List<String> suffix; private List<DataSourceDetailProperties> db; }
在jar包的Configuration中,某個@Bean的構造過程中引用了這個DataSourceProperties
public JdbcTemplate buildJdbcTemplate(DataSourceProperties dataSourceProperties) { }
在某個業務場景中,同時存在兩個DataSourceProperties 會造成一個問題,注入的時候會提示有多個候選的bean 但是沒法去修改Jar包中的內容
自己重復寫一個DataSourceProperties 不是很優雅
這時候引出了一個需求,DataSourceProperties不希望注冊為Bean,但是能夠從配置文件讀取構建對象
使用org.springframework.boot.context.properties.bind.Binder
從配置文件構建配置對象
@Bean public JdbcTemplate buildJdbcTemplate(Environment environment) { Binder binder = Binder.get(environment); DataSourceProperties properties1 = binder.bind("my.datasource1", Bindable.of(DataSourceProperties.class)).get(), properties2 = binder.bind("my.datasource2", Bindable.of(DataSourceProperties.class)).get(); }
binder.bind("xxx", Bindable.of(type)).get() 似乎是重復的編碼方式?
使@Value
注解能夠支持自動調用這段代碼 binder.bind("xxx", Bindable.of(type)).get()
例如
@Bean public JdbcTemplate buildJdbcTemplate(@Value("my.datasource1") DataSourceProperties properties1, @Value("my.datasource2") DataSourceProperties properties2) { }
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
最后會交由converter處理
Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { // A custom TypeConverter which does not support TypeDescriptor resolution... return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } }
項目啟動時,添加String to Object的轉換器,支持@Value
并且 "bind:"開頭(防止影響@Value
原有功能)
package com.nuonuo.accounting.guiding.support.spring; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.convert.ApplicationConversionService; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import java.util.Set; import static java.util.Collections.singleton; /** * @author uhfun */ public class ValuePropertiesBindableAnnotationSupport implements ApplicationContextInitializer<ConfigurableApplicationContext> { private static final String PREFIX = "bind:"; @Override public void initialize(ConfigurableApplicationContext context) { Binder binder = Binder.get(context.getEnvironment()); ((ApplicationConversionService) context.getBeanFactory().getConversionService()).addConverter(new ConditionalGenericConverter() { @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { Value value = targetType.getAnnotation(Value.class); return value != null && value.value().startsWith(PREFIX); } @Override public Set<ConvertiblePair> getConvertibleTypes() { return singleton(new ConvertiblePair(String.class, Object.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { Value value = targetType.getAnnotation(Value.class); Class<?> type = targetType.getType(); assert value != null; return binder.bind(value.value().replace(PREFIX, ""), Bindable.of(type)).get(); } }); } }
轉換后代碼執行 binder.bind(value.value().replace(PREFIX, ""), Bindable.of(type)).get();
目的就達成了
在META-INF/spring.factories
中添加注冊的Bean
# ApplicationContextInitializer org.springframework.context.ApplicationContextInitializer=\ com.nuonuo.accounting.guiding.support.spring.ValuePropertiesBindableAnnotationSupport,\
最終效果
@Bean public JdbcTemplate buildJdbcTemplate(@Value("bind:my.datasource1") DataSourceProperties properties1, @Value("bind:my.datasource2") DataSourceProperties properties2) { }
到此,相信大家對“Value注解支持對象類型ConfigurationProperties功能問題怎么解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。