@EnableConfigurationProperties和@ConfigurationProperties的区别

@EnableConfigurationProperties和@ConfigurationProperties的区别

在springboot的开发中我们经常会使用到@ConfigurationProperties赖获取配置的值绑定到项目中的bean中,要完成这个功能核心的注解是@ConfigurationProperties。但是在项目中经常看到另外一个注解@EnableConfigurationProperties也是为了实现类似的功能,那么它们之间有什么关系呢?

区别

@EnableConfigurationProperties的作用有两个:
1、导入EnableConfigurationPropertiesRegistrarc.class这个类,这个类会向容器中注册ConfigurationPropertiesBindingPostProcessor处理器
2、该注解有value属性,需要填入class对象。只要填入的class被标记了@ConfigurationProperties注解,那么该class无需注册为spring的Bean,它默认会创建这个Bean并绑定配置值注册到容器中。

@ConfigurationProperties的作用:
配合ConfigurationPropertiesBindingPostProcessor这个BeanPostProcessor完成配置值绑定到目标Bean。

使用配置绑定到Bean这个功能需要先开启@EnableConfigurationProperties才能使@ConfigurationProperties生效。但是实际项目中我们确实可以不用手动开启@EnableConfigurationProperties就能使用@ConfigurationProperties,原因是springboot的自动配置很多都用到了@EnableConfigurationProperties这个注解,一旦这个注解被触发,那我们在项目中就可以直接使用而不需要开启。

@EnableConfigurationProperties

@EnableConfigurationProperties注解导入了EnableConfigurationPropertiesRegistrar.class,该class实现了ImportBeanDefinitionRegistrar类,会向spring容器注册核心类ConfigurationPropertiesBindingPostProcessor,这个class实现了spring容器周期的BeanPostProcessor接口,在周期方法postProcessBeforeInitialization中会解析每个bean,如果某个bean被标记了@ConfigurationProperties注解,那么会把配置值绑定到此bean中。

package org.springframework.boot.context.properties;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({EnableConfigurationPropertiesRegistrar.class})
public @interface EnableConfigurationProperties {
    String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";

    Class<?>[] value() default {};
}

@EnableConfigurationProperties 注解

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(2);
            registry.registerBeanDefinition(BEAN_NAME, definition);
        }

        ConfigurationPropertiesBinder.register(registry);
    }

导入类EnableConfigurationPropertiesRegistrar会向容器注入ConfigurationPropertiesBindingPostProcessor处理器,这里的BEAN_NAME就是ConfigurationPropertiesBindingPostProcessor类的全限定名。ConfigurationPropertiesBinder.register(registry);向容器中注册ConfigurationPropertiesBinder,该对象是真正的绑定逻辑执行者,会从容器的environment对象中获取值绑定到目标Bean中

/**
* EnableConfigurationPropertiesRegistrar类注册代码
* registerInfrastructureBeans(registry); 注册ConfigurationPropertiesBindingPostProcessor
*/
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        registerInfrastructureBeans(registry);
        registerMethodValidationExcludeFilter(registry);
        ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
        this.getTypes(metadata).forEach(beanRegistrar::register);
    }
    
 private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
        return (Set)metadata.getAnnotations().stream(EnableConfigurationProperties.class).flatMap((annotation) -> {
            return Arrays.stream(annotation.getClassArray("value"));
        }).filter((type) -> {
            return Void.TYPE != type;
        }).collect(Collectors.toSet());
    }

this.getTypes(metadata).forEach(beanRegistrar::register);如果@EnableConfigurationProperties 注解的value属性(数组Class)有值,那么将继续探测类(数组中的Class)上是否有@ConfigurationProperties,如果有,那么注册这个类到容器中,后续创建Bean时配合ConfigurationPropertiesBindingPostProcessor绑定值。

@ConfigurationProperties

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

执行的是ConfigurationPropertiesBindingPostProcessor中的绑定方法

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值