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

springboot?ConfigurationProperties的綁定源碼示例解析

 更新時(shí)間:2023年09月07日 10:01:39   作者:codecraft  
這篇文章主要為大家介紹了springboot?ConfigurationProperties的綁定源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下springboot的ConfigurationProperties的綁定

ConfigurationPropertiesBindingPostProcessor

org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java

/**
 * {@link BeanPostProcessor} to bind {@link PropertySources} to beans annotated with
 * {@link ConfigurationProperties @ConfigurationProperties}.
 *
 * @author Dave Syer
 * @author Phillip Webb
 * @author Christian Dupuis
 * @author Stephane Nicoll
 * @author Madhura Bhave
 * @since 1.0.0
 */
public class ConfigurationPropertiesBindingPostProcessor
        implements BeanPostProcessor, PriorityOrdered, ApplicationContextAware, InitializingBean {
    /**
     * The bean name that this post-processor is registered with.
     */
    public static final String BEAN_NAME = ConfigurationPropertiesBindingPostProcessor.class.getName();
    private ApplicationContext applicationContext;
    private BeanDefinitionRegistry registry;
    private ConfigurationPropertiesBinder binder;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        // We can't use constructor injection of the application context because
        // it causes eager factory bean initialization
        this.registry = (BeanDefinitionRegistry) this.applicationContext.getAutowireCapableBeanFactory();
        this.binder = ConfigurationPropertiesBinder.get(this.applicationContext);
    }
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 1;
    }
    @Override
    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 {
            this.binder.bind(bean);
        }
        catch (Exception ex) {
            throw new ConfigurationPropertiesBindException(bean, ex);
        }
    }
    private boolean hasBoundValueObject(String beanName) {
        return this.registry.containsBeanDefinition(beanName) && this.registry
                .getBeanDefinition(beanName) instanceof ConfigurationPropertiesValueObjectBeanDefinition;
    }
    /**
     * Register a {@link ConfigurationPropertiesBindingPostProcessor} bean if one is not
     * already registered.
     * @param registry the bean definition registry
     * @since 2.2.0
     */
    public static void register(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "Registry must not be null");
        if (!registry.containsBeanDefinition(BEAN_NAME)) {
            BeanDefinition definition = BeanDefinitionBuilder
                    .genericBeanDefinition(ConfigurationPropertiesBindingPostProcessor.class,
                            ConfigurationPropertiesBindingPostProcessor::new)
                    .getBeanDefinition();
            definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(BEAN_NAME, definition);
        }
        ConfigurationPropertiesBinder.register(registry);
    }
}
ConfigurationPropertiesBindingPostProcessor實(shí)現(xiàn)了BeanPostProcessor、PriorityOrdered、ApplicationContextAware、InitializingBean四個(gè)接口;其getOrder方法返回的是Ordered.HIGHEST_PRECEDENCE + 1即僅次于最高的優(yōu)先級(jí);其postProcessBeforeInitialization方法主要是執(zhí)行bind方法(先通過(guò)ConfigurationPropertiesBean.get獲取ConfigurationPropertiesBean,再通過(guò)binder進(jìn)行bind);其afterPropertiesSet主要是獲取BeanDefinitionRegistry與ConfigurationPropertiesBinder

ConfigurationPropertiesBean.get

org/springframework/boot/context/properties/ConfigurationPropertiesBean.java

public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) {
        Method factoryMethod = findFactoryMethod(applicationContext, beanName);
        return create(beanName, bean, bean.getClass(), factoryMethod);
    }
    private static ConfigurationPropertiesBean create(String name, Object instance, Class<?> type, Method factory) {
        ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class);
        if (annotation == null) {
            return null;
        }
        Validated validated = findAnnotation(instance, type, factory, Validated.class);
        Annotation[] annotations = (validated != null) ? new Annotation[] { annotation, validated }
                : new Annotation[] { annotation };
        ResolvableType bindType = (factory != null) ? ResolvableType.forMethodReturnType(factory)
                : ResolvableType.forClass(type);
        Bindable<Object> bindTarget = Bindable.of(bindType).withAnnotations(annotations);
        if (instance != null) {
            bindTarget = bindTarget.withExistingValue(instance);
        }
        return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget);
    }
get方法主要是獲取工廠方法,之后獲取annotation,獲取bindTarget,最后創(chuàng)建ConfigurationPropertiesBean

ConfigurationPropertiesBean

org/springframework/boot/context/properties/ConfigurationPropertiesBean.java

/**
 * Provides access to {@link ConfigurationProperties @ConfigurationProperties} bean
 * details, regardless of if the annotation was used directly or on a {@link Bean @Bean}
 * factory method. This class can be used to access {@link #getAll(ApplicationContext)
 * all} configuration properties beans in an ApplicationContext, or
 * {@link #get(ApplicationContext, Object, String) individual beans} on a case-by-case
 * basis (for example, in a {@link BeanPostProcessor}).
 *
 * @author Phillip Webb
 * @since 2.2.0
 * @see #getAll(ApplicationContext)
 * @see #get(ApplicationContext, Object, String)
 */
public final class ConfigurationPropertiesBean {
    private final String name;
    private final Object instance;
    private final ConfigurationProperties annotation;
    private final Bindable<?> bindTarget;
    private final BindMethod bindMethod;
    //......
}
ConfigurationPropertiesBean用于代表一個(gè)標(biāo)注了@ConfigurationProperties注解的bean的信息

ConfigurationPropertiesBinder

org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java

/**
 * Internal class used by the {@link ConfigurationPropertiesBindingPostProcessor} to
 * handle the actual {@link ConfigurationProperties @ConfigurationProperties} binding.
 *
 * @author Stephane Nicoll
 * @author Phillip Webb
 */
class ConfigurationPropertiesBinder {
    private static final String BEAN_NAME = "org.springframework.boot.context.internalConfigurationPropertiesBinder";
    private static final String FACTORY_BEAN_NAME = "org.springframework.boot.context.internalConfigurationPropertiesBinderFactory";
    private static final String VALIDATOR_BEAN_NAME = EnableConfigurationProperties.VALIDATOR_BEAN_NAME;
    private final ApplicationContext applicationContext;
    private final PropertySources propertySources;
    private final Validator configurationPropertiesValidator;
    private final boolean jsr303Present;
    private volatile Validator jsr303Validator;
    private volatile Binder binder;
    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(),
                    getConversionService(), getPropertyEditorInitializer(), null,
                    ConfigurationPropertiesBindConstructorProvider.INSTANCE);
        }
        return this.binder;
    }
    //......
}
ConfigurationPropertiesBinder的bind方法根據(jù)ConfigurationPropertiesBean的target與annotation取獲取bindHandler,然后通過(guò)binder去執(zhí)行bind方法
binder的構(gòu)造器依賴了propertySources、placeholdersResolver、conversionService、propertyEditorInitializer、defaultBindHandler、constructorProvider

Binder

org/springframework/boot/context/properties/bind/Binder.java

private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
            Context context, boolean allowRecursiveBinding) {
        ConfigurationProperty property = findProperty(name, context);
        if (property == null && context.depth != 0 && containsNoDescendantOf(context.getSources(), name)) {
            return null;
        }
        AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context);
        if (aggregateBinder != null) {
            return bindAggregate(name, target, handler, context, aggregateBinder);
        }
        if (property != null) {
            try {
                return bindProperty(target, context, property);
            }
            catch (ConverterNotFoundException ex) {
                // We might still be able to bind it using the recursive binders
                Object instance = bindDataObject(name, target, handler, context, allowRecursiveBinding);
                if (instance != null) {
                    return instance;
                }
                throw ex;
            }
        }
        return bindDataObject(name, target, handler, context, allowRecursiveBinding);
    }
    private AggregateBinder<?> getAggregateBinder(Bindable<?> target, Context context) {
        Class<?> resolvedType = target.getType().resolve(Object.class);
        if (Map.class.isAssignableFrom(resolvedType)) {
            return new MapBinder(context);
        }
        if (Collection.class.isAssignableFrom(resolvedType)) {
            return new CollectionBinder(context);
        }
        if (target.getType().isArray()) {
            return new ArrayBinder(context);
        }
        return null;
    }
    private <T> Object bindAggregate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
            Context context, AggregateBinder<?> aggregateBinder) {
        AggregateElementBinder elementBinder = (itemName, itemTarget, source) -> {
            boolean allowRecursiveBinding = aggregateBinder.isAllowRecursiveBinding(source);
            Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false);
            return context.withSource(source, supplier);
        };
        return context.withIncreasedDepth(() -> aggregateBinder.bind(name, target, elementBinder));
    }
    private <T> Object bindProperty(Bindable<T> target, Context context, ConfigurationProperty property) {
        context.setConfigurationProperty(property);
        Object result = property.getValue();
        result = this.placeholdersResolver.resolvePlaceholders(result);
        result = context.getConverter().convert(result, target);
        return result;
    }
bindObject方法先通過(guò)findProperty獲取ConfigurationProperty,然后執(zhí)行bindAggregate或者bindProperty;AggregateBinder主要是處理Map、Collection、Array類型;bindProperty方法這里從property獲取綁定的值,然后resolvePlaceholders,最后通過(guò)converter的convert方法把值綁定到target上

BindConverter

org/springframework/boot/context/properties/bind/BindConverter.java

<T> T convert(Object value, ResolvableType type, Annotation... annotations) {
        if (value == null) {
            return null;
        }
        return (T) this.conversionService.convert(value, TypeDescriptor.forObject(value),
                new ResolvableTypeDescriptor(type, annotations));
    }
BindConverter的convert方法則是通過(guò)conversionService進(jìn)行

小結(jié)

ConfigurationPropertiesBindingPostProcessor實(shí)現(xiàn)了BeanPostProcessor、PriorityOrdered、ApplicationContextAware、InitializingBean四個(gè)接口;

其getOrder方法返回的是Ordered.HIGHEST_PRECEDENCE + 1即僅次于最高的優(yōu)先級(jí);

其postProcessBeforeInitialization方法主要是執(zhí)行bind方法(先通過(guò)ConfigurationPropertiesBean.get獲取ConfigurationPropertiesBean,再通過(guò)binder進(jìn)行bind);

其afterPropertiesSet主要是獲取BeanDefinitionRegistry與ConfigurationPropertiesBinder

以上就是springboot ConfigurationProperties的綁定源碼示例解析的詳細(xì)內(nèi)容,更多關(guān)于springboot ConfigurationProperties綁定的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Vue.js和Ant Design Vue實(shí)現(xiàn)根據(jù)字段內(nèi)容動(dòng)態(tài)設(shè)置表格顏色功能

    基于Vue.js和Ant Design Vue實(shí)現(xiàn)根據(jù)字段內(nèi)容動(dòng)態(tài)設(shè)置表格顏色功能

    在前端開(kāi)發(fā)中,表格Table是展示數(shù)據(jù)的常見(jiàn)組件,有時(shí),我們需要根據(jù)表格中某些字段的內(nèi)容動(dòng)態(tài)設(shè)置樣式,例如根據(jù)百分比數(shù)值顯示不同的顏色,以提升數(shù)據(jù)的可讀性和用戶體驗(yàn),本文將詳細(xì)介紹如何基于Vue.js和Ant Design Vue實(shí)現(xiàn)這一功能,并結(jié)合實(shí)際代碼示例進(jìn)行解析
    2025-06-06
  • JavaWeb實(shí)現(xiàn)RSA+AES混合加密

    JavaWeb實(shí)現(xiàn)RSA+AES混合加密

    RSA+AES的混合加密時(shí),AES用于給傳輸?shù)臄?shù)據(jù)加密,然后通過(guò)RSA給AES的秘鑰加密,本文就來(lái)詳細(xì)的介紹一下如何實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • Java AQS(AbstractQueuedSynchronizer)源碼解析

    Java AQS(AbstractQueuedSynchronizer)源碼解析

    AbstractQueuedSynchronizer被稱為隊(duì)列同步器,簡(jiǎn)稱為大家熟知的AQS,這個(gè)類可以稱作concurrent包的基礎(chǔ)。本文將通過(guò)剖析源碼來(lái)看看AQS是如何工作的,感興趣的可以了解一下
    2023-02-02
  • Mybatis-Plus默認(rèn)主鍵策略導(dǎo)致自動(dòng)生成19位長(zhǎng)度主鍵id的坑

    Mybatis-Plus默認(rèn)主鍵策略導(dǎo)致自動(dòng)生成19位長(zhǎng)度主鍵id的坑

    這篇文章主要介紹了Mybatis-Plus默認(rèn)主鍵策略導(dǎo)致自動(dòng)生成19位長(zhǎng)度主鍵id的坑,本文一步步給大家分享解決方法,給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • SpringBoot返回統(tǒng)一的JSON標(biāo)準(zhǔn)格式實(shí)現(xiàn)步驟

    SpringBoot返回統(tǒng)一的JSON標(biāo)準(zhǔn)格式實(shí)現(xiàn)步驟

    這篇文章主要介紹了SpringBoot返回統(tǒng)一的JSON標(biāo)準(zhǔn)格式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Java單例模式的線程安全,餓漢和懶漢模式詳解

    Java單例模式的線程安全,餓漢和懶漢模式詳解

    這篇文章主要為大家詳細(xì)介紹了Java單例模式的線程安全,餓漢和懶漢模式。文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • Java selenium截圖操作的實(shí)現(xiàn)

    Java selenium截圖操作的實(shí)現(xiàn)

    這篇文章主要介紹了Java selenium截圖操作的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Lombok的@Data等注解無(wú)效的解決

    Lombok的@Data等注解無(wú)效的解決

    這篇文章主要介紹了Lombok的@Data等注解無(wú)效的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 全面解釋java中StringBuilder、StringBuffer、String類之間的關(guān)系

    全面解釋java中StringBuilder、StringBuffer、String類之間的關(guān)系

    String的值是不可變的,這就導(dǎo)致每次對(duì)String的操作都會(huì)生成新的String對(duì)象,不僅效率低下,而且大量浪費(fèi)有限的內(nèi)存空間,StringBuffer是可變類,和線程安全的字符串操作類,任何對(duì)它指向的字符串的操作都不會(huì)產(chǎn)生新的對(duì)象,StringBuffer和StringBuilder類功能基本相似
    2013-01-01
  • Java讀取XML實(shí)現(xiàn)過(guò)程(DOM方式)

    Java讀取XML實(shí)現(xiàn)過(guò)程(DOM方式)

    文章介紹了如何使用Java的DOM方式讀取XML文件,并詳細(xì)說(shuō)明了讀取過(guò)程中需要注意的事項(xiàng),如文件路徑、節(jié)點(diǎn)層級(jí)和屬性值的獲取方式,作者通過(guò)一個(gè)示例代碼展示了如何實(shí)現(xiàn)XML的讀取,并總結(jié)了自己的經(jīng)驗(yàn),希望對(duì)讀者有所幫助
    2025-11-11

最新評(píng)論

汶川县| 新和县| 潼南县| 博野县| 上蔡县| 孟村| 岐山县| 阳曲县| 什邡市| 班戈县| 双牌县| 高邑县| 仙桃市| 广南县| 定远县| 英德市| 晋中市| 武城县| 游戏| 瑞安市| 红原县| 寿光市| 阿坝县| 瑞金市| 唐河县| 六枝特区| 内乡县| 彰武县| 广宁县| 潮安县| 武宁县| 肃北| 突泉县| 绥中县| 屏山县| 鹤岗市| 定襄县| 怀化市| 汉沽区| 清涧县| 比如县|