SpringBoot ConfigurationProperties

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-spring-boot

  • 本文主要对org.springframework.boot.context.properties.ConfigurationProperties进行分析

ConfigurationProperties

  • 顶部注释
  1. * @see ConfigurationPropertiesScan
  2. * @see ConstructorBinding
  3. * @see ConfigurationPropertiesBindingPostProcessor
  4. * @see EnableConfigurationProperties

看到ConfigurationPropertiesScan 去看看这个

ConfigurationPropertiesScan

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(ConfigurationPropertiesScanRegistrar.class)
  5. @EnableConfigurationProperties
  6. public @interface ConfigurationPropertiesScan {}
  • 熟悉的Import注解

ConfigurationPropertiesScanRegistrar

image-20200323094446756

  • debug 没有抓到后续补充

EnableConfigurationProperties

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(EnableConfigurationPropertiesRegistrar.class)
  5. public @interface EnableConfigurationProperties {
  6. }

EnableConfigurationPropertiesRegistrar

  • 该类会读取spring.factories

  • org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 这样的

    1. org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
    2. org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
    3. org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
    4. org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
    5. org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
    6. org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter
    7. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
    8. org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration
    9. org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration
    10. org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
    11. org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration
    12. org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
    13. org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
    14. org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
    15. org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
  1. @Override
  2. public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
  3. // 注册bean
  4. registerInfrastructureBeans(registry);
  5. // 配置属性Bean注册器
  6. ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
  7. // 循环注册
  8. getTypes(metadata).forEach(beanRegistrar::register);
  9. }

registerInfrastructureBeans

  1. static void registerInfrastructureBeans(BeanDefinitionRegistry registry) {
  2. // 属性绑定后置处理器
  3. ConfigurationPropertiesBindingPostProcessor.register(registry);
  4. // 属性校验器
  5. ConfigurationPropertiesBeanDefinitionValidator.register(registry);
  6. ConfigurationBeanFactoryMetadata.register(registry);
  7. }
  • 此处操作逻辑基本相同,是否存在这个 beanName 存在直接注册,不存在补充

ConfigurationPropertiesBindingPostProcessor.register(registry)

  1. public static void register(BeanDefinitionRegistry registry) {
  2. Assert.notNull(registry, "Registry must not be null");
  3. // 是否存在
  4. if (!registry.containsBeanDefinition(BEAN_NAME)) {
  5. GenericBeanDefinition definition = new GenericBeanDefinition();
  6. definition.setBeanClass(ConfigurationPropertiesBindingPostProcessor.class);
  7. definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  8. registry.registerBeanDefinition(BEAN_NAME, definition);
  9. }
  10. ConfigurationPropertiesBinder.register(registry);
  11. }

ConfigurationPropertiesBeanDefinitionValidator.register(registry)

  1. static void register(BeanDefinitionRegistry registry) {
  2. Assert.notNull(registry, "Registry must not be null");
  3. if (!registry.containsBeanDefinition(BEAN_NAME)) {
  4. GenericBeanDefinition definition = new GenericBeanDefinition();
  5. definition.setBeanClass(ConfigurationPropertiesBeanDefinitionValidator.class);
  6. definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  7. registry.registerBeanDefinition(BEAN_NAME, definition);
  8. }
  9. ConfigurationPropertiesBinder.register(registry);
  10. }

getTypes(metadata).forEach(beanRegistrar::register)

  • 先看输入参数 metadata

image-20200323134135926

  • getTypes 结果

image-20200323134325955

  • 源码开始,先找出刚才的对象org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

    1. @Configuration(proxyBeanMethods = false)
    2. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    3. @ConditionalOnClass(ServletRequest.class)
    4. @ConditionalOnWebApplication(type = Type.SERVLET)
    5. @EnableConfigurationProperties(ServerProperties.class)
    6. @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
    7. ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
    8. ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
    9. ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    10. public class ServletWebServerFactoryAutoConfiguration {}
  1. /**
  2. * 找出 {@link EnableConfigurationProperties} 注解标记的中的属性值,并且返回值不是void
  3. * @param metadata
  4. * @return
  5. */
  6. private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
  7. return
  8. metadata.getAnnotations().stream(EnableConfigurationProperties.class)
  9. .flatMap((annotation) -> Arrays.stream(annotation.getClassArray(MergedAnnotation.VALUE)))
  10. .filter((type) -> void.class != type).collect(Collectors.toSet());
  11. }
  • 这里我们可以直接知道返回的是@EnableConfigurationProperties(ServerProperties.class) 的数据值: ServerProperties.class

循环注册

  1. void register(Class<?> type) {
  2. MergedAnnotation<ConfigurationProperties> annotation = MergedAnnotations
  3. .from(type, SearchStrategy.TYPE_HIERARCHY).get(ConfigurationProperties.class);
  4. register(type, annotation);
  5. }

ConfigurationPropertiesBindingPostProcessor

image-20200323095626953

postProcessBeforeInitialization

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  3. // 绑定
  4. bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
  5. return bean;
  6. }
  • get

    1. public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) {
    2. // 寻找工厂方法
    3. Method factoryMethod = findFactoryMethod(applicationContext, beanName);
    4. // 创建 ConfigurationPropertiesBean
    5. return create(beanName, bean, bean.getClass(), factoryMethod);
    6. }
  1. private static Method findFactoryMethod(ConfigurableListableBeanFactory beanFactory, String beanName) {
  2. // 判断是否存在这个beanName
  3. if (beanFactory.containsBeanDefinition(beanName)) {
  4. // 获取bean定义
  5. BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
  6. // 类型判断
  7. if (beanDefinition instanceof RootBeanDefinition) {
  8. // 解析方法
  9. Method resolvedFactoryMethod = ((RootBeanDefinition) beanDefinition).getResolvedFactoryMethod();
  10. if (resolvedFactoryMethod != null) {
  11. return resolvedFactoryMethod;
  12. }
  13. }
  14. return findFactoryMethodUsingReflection(beanFactory, beanDefinition);
  15. }
  16. return null;
  17. }
  1. private static Method findFactoryMethodUsingReflection(ConfigurableListableBeanFactory beanFactory,
  2. BeanDefinition beanDefinition) {
  3. // 工厂方法
  4. String factoryMethodName = beanDefinition.getFactoryMethodName();
  5. // 工厂bean
  6. String factoryBeanName = beanDefinition.getFactoryBeanName();
  7. if (factoryMethodName == null || factoryBeanName == null) {
  8. return null;
  9. }
  10. // 转换对象
  11. Class<?> factoryType = beanFactory.getType(factoryBeanName);
  12. if (factoryType.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
  13. factoryType = factoryType.getSuperclass();
  14. }
  15. AtomicReference<Method> factoryMethod = new AtomicReference<>();
  16. ReflectionUtils.doWithMethods(factoryType, (method) -> {
  17. // 判断是否是需要的方法
  18. if (method.getName().equals(factoryMethodName)) {
  19. // 设置方法
  20. factoryMethod.set(method);
  21. }
  22. });
  23. // 返回方法
  24. return factoryMethod.get();
  25. }

create

  • org.springframework.boot.context.properties.ConfigurationPropertiesBean#create
  1. private static ConfigurationPropertiesBean create(String name, Object instance, Class<?> type, Method factory) {
  2. // 找注解
  3. ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class);
  4. if (annotation == null) {
  5. return null;
  6. }
  7. // 找注解
  8. Validated validated = findAnnotation(instance, type, factory, Validated.class);
  9. // 注解列表
  10. Annotation[] annotations = (validated != null) ? new Annotation[] { annotation, validated }
  11. : new Annotation[] { annotation };
  12. // 类型解析
  13. ResolvableType bindType = (factory != null) ? ResolvableType.forMethodReturnType(factory)
  14. : ResolvableType.forClass(type);
  15. // 绑定结果对象
  16. Bindable<Object> bindTarget = Bindable.of(bindType).withAnnotations(annotations);
  17. if (instance != null) {
  18. bindTarget = bindTarget.withExistingValue(instance);
  19. }
  20. return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget);
  21. }
  • 第一个需要做的类: org.springframework.boot.autoconfigure.web.ServerProperties

  • annotation

image-20200323104711545

  • bindType

image-20200323104815305

  • 返回对象

image-20200323105053757

  • 此时数据还没有进去

bind

  • 数据绑定

直接看结果

image-20200323105155998

  • 上述配置和我在配置文件中写的配置一致
  1. server:
  2. port: 9999
  • 具体方法: org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor#bind
  1. private void bind(ConfigurationPropertiesBean bean) {
  2. if (bean == null || hasBoundValueObject(bean.getName())) {
  3. return;
  4. }
  5. Assert.state(bean.getBindMethod() == BindMethod.JAVA_BEAN, "Cannot bind @ConfigurationProperties for bean '"
  6. + bean.getName() + "'. Ensure that @ConstructorBinding has not been applied to regular bean");
  7. try {
  8. // 最终的绑定
  9. this.binder.bind(bean);
  10. }
  11. catch (Exception ex) {
  12. throw new ConfigurationPropertiesBindException(bean, ex);
  13. }
  14. }
  1. BindResult<?> bind(ConfigurationPropertiesBean propertiesBean) {
  2. // 最后的结果
  3. Bindable<?> target = propertiesBean.asBindTarget();
  4. // 注解获取
  5. ConfigurationProperties annotation = propertiesBean.getAnnotation();
  6. // 获取处理器
  7. BindHandler bindHandler = getBindHandler(target, annotation);
  8. //
  9. return getBinder().bind(annotation.prefix(), target, bindHandler);
  10. }

image-20200323105830138

findProperty
  1. private ConfigurationProperty findProperty(ConfigurationPropertyName name, Context context) {
  2. if (name.isEmpty()) {
  3. return null;
  4. }
  5. for (ConfigurationPropertySource source : context.getSources()) {
  6. // 获取具体的一个属性值
  7. ConfigurationProperty property = source.getConfigurationProperty(name);
  8. if (property != null) {
  9. return property;
  10. }
  11. }
  12. return null;
  13. }
  • org.springframework.boot.context.properties.source.SpringConfigurationPropertySource#getConfigurationProperty

    1. @Override
    2. public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
    3. PropertyMapping[] mappings = getMapper().map(name);
    4. return find(mappings, name);
    5. }
    1. protected final ConfigurationProperty find(PropertyMapping[] mappings, ConfigurationPropertyName name) {
    2. for (PropertyMapping candidate : mappings) {
    3. if (candidate.isApplicable(name)) {
    4. ConfigurationProperty result = find(candidate);
    5. if (result != null) {
    6. return result;
    7. }
    8. }
    9. }
    10. return null;
    11. }
    1. private ConfigurationProperty find(PropertyMapping mapping) {
    2. // 需要读取的配置信息的key
    3. String propertySourceName = mapping.getPropertySourceName();
    4. // 信息的value
    5. Object value = getPropertySource().getProperty(propertySourceName);
    6. if (value == null) {
    7. return null;
    8. }
    9. // 创建对象
    10. ConfigurationPropertyName configurationPropertyName = mapping.getConfigurationPropertyName();
    11. Origin origin = PropertySourceOrigin.get(this.propertySource, propertySourceName);
    12. // 包装返回
    13. return ConfigurationProperty.of(configurationPropertyName, value, origin);
    14. }

image-20200323115408877

image-20200323115701118

image-20200323115711826

getBindHandler
  1. private <T> BindHandler getBindHandler(Bindable<T> target, ConfigurationProperties annotation) {
  2. // 获取校验接口列表
  3. List<Validator> validators = getValidators(target);
  4. // 处理器
  5. BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler();
  6. if (annotation.ignoreInvalidFields()) {
  7. // 忽略错误的绑定处理器
  8. handler = new IgnoreErrorsBindHandler(handler);
  9. }
  10. if (!annotation.ignoreUnknownFields()) {
  11. UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter();
  12. // 未绑定元素处理器
  13. handler = new NoUnboundElementsBindHandler(handler, filter);
  14. }
  15. if (!validators.isEmpty()) {
  16. // 校验绑定处理器
  17. handler = new ValidationBindHandler(handler, validators.toArray(new Validator[0]));
  18. }
  19. for (ConfigurationPropertiesBindHandlerAdvisor advisor : getBindHandlerAdvisors()) {
  20. // handler
  21. handler = advisor.apply(handler);
  22. }
  23. return handler;
  24. }
  • 最终获取得到的处理器

image-20200323110603959

  • 最后的 bind
  1. private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
  2. Context context, boolean allowRecursiveBinding) {
  3. // 获取属性
  4. ConfigurationProperty property = findProperty(name, context);
  5. if (property == null && containsNoDescendantOf(context.getSources(), name) && context.depth != 0) {
  6. return null;
  7. }
  8. AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context);
  9. if (aggregateBinder != null) {
  10. return bindAggregate(name, target, handler, context, aggregateBinder);
  11. }
  12. if (property != null) {
  13. try {
  14. return bindProperty(target, context, property);
  15. }
  16. catch (ConverterNotFoundException ex) {
  17. // We might still be able to bind it using the recursive binders
  18. Object instance = bindDataObject(name, target, handler, context, allowRecursiveBinding);
  19. if (instance != null) {
  20. return instance;
  21. }
  22. throw ex;
  23. }
  24. }
  25. return bindDataObject(name, target, handler, context, allowRecursiveBinding);
  26. }

image-20200323112945449

配置信息到此绑定成功,关于如何处理集合相关的配置请各位读者自行学习