美文网首页
springboot源码-自动化配置

springboot源码-自动化配置

作者: 无聊之园 | 来源:发表于2024-03-11 12:00 被阅读0次

    总结:
    1、EnableAutoConfiguration自动化配置类有很多实现类,各个实现类会自动化解析yml文件的属性,绑定到实例类中。比如server.port属性会通过ServletWebServerFactoryAutoConfiguration自动化配置类绑定到ServerProperties对象中,然后把这个对象注入到ioc容器。
    2、绑定的方式就是自动化配置类比如ServletWebServerFactoryAutoConfiguration,通过注解@EnableConfigurationProperties(ServerProperties.class)完成。
    3、注解@EnableConfigurationProperties(ServerProperties.class)注解,是通过注册器@Import(EnableConfigurationPropertiesRegistrar.class),EnableConfigurationPropertiesRegistrar类首先会构建一个ConfigurationPropertiesBindingPostProcessor配置属性绑定后置处理器,并注入到ioc容器(这个后置处理器的作用就是构建bean之后,触发afterPropertiesSet方法,从ConfigurationPropertySource属性列表中获取对应的属性,绑定到bean对象比如ServerProperties中)。再通过注解元数据信息类AnnotationMetadata获取到需要绑定的对象类:ServerProperties。然后构建对象,注入ioc,然后触发ConfigurationPropertiesBindingPostProcessor的afterPropertiesSet方法绑定属性。

    比如,application.yml的配置,是如何解析到springboot的

    server:
      port: 8080
    

    在META-INF/spring.factories里可以看到EnableAutoConfiguration的实现类有一个ServletWebServerFactoryAutoConfiguration。前面说了spring boot启动的时候会解析所有EnableAutoConfiguration的实现类,并实例化。

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
    
    

    可以看到这个类有注解:@EnableConfigurationProperties(ServerProperties.class)

    @Configuration(proxyBeanMethods = false)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @ConditionalOnClass(ServletRequest.class)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @EnableConfigurationProperties(ServerProperties.class)
    @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
            ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
            ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
            ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    public class ServletWebServerFactoryAutoConfiguration {
    
    @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
    public class ServerProperties {
    
        /**
         * Server HTTP port.
         */
        private Integer port;
    }
    
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ConfigurationProperties {
    

    可以看到@Import(EnableConfigurationPropertiesRegistrar.class)。
    首先会注入ConfigurationPropertiesBindingPostProcessor对象到ioc容器,这个对象是一个BeanPostProcessor,所以会在对象实例化之后调用afterPropertiesSet方法(这段可以看spring ioc的源码理解)。
    这个ConfigurationPropertiesBindingPostProcessor类的作用就是绑定@EnableConfigurationProperties(ServerProperties.class)注解上的ServerProperties类的属性。绑定的方式就是从获取ConfigurationPropertySource对象列表遍历获取值(之前分析过解析yaml文件或properties文件的属性都会保存为ConfigurationPropertySource,解析逻辑在之前的源码分析里)

    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(EnableConfigurationPropertiesRegistrar.class)
    public @interface EnableConfigurationProperties {
    }
    
    @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 注册一些基础类到ioc,不管   
                registerInfrastructureBeans(registry);
            registerMethodValidationExcludeFilter(registry);
    // 构建ConfigurationPropertiesBeanRegistrar 对象,没做其他的事情
        ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
    // // 获取@EnableConfigurationProperties(ServerProperties.class)注解上的ServerProperties注解。然后
            getTypes(metadata).forEach(beanRegistrar::register);
        }
    // 获取@EnableConfigurationProperties(ServerProperties.class)注解上的ServerProperties注解。
    private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
            return metadata.getAnnotations().stream(EnableConfigurationProperties.class)
                    .flatMap((annotation) -> Arrays.stream(annotation.getClassArray(MergedAnnotation.VALUE)))
                    .filter((type) -> void.class != type).collect(Collectors.toSet());
        }
    
    static void registerInfrastructureBeans(BeanDefinitionRegistry registry) {
            ConfigurationPropertiesBindingPostProcessor.register(registry);
            BoundConfigurationProperties.register(registry);
        }
    
    

    具体的绑定属性逻辑

    private ConfigurationProperty findProperty(ConfigurationPropertyName name, Context context) {
            if (name.isEmpty()) {
                return null;
            }
            for (ConfigurationPropertySource source : context.getSources()) {
                ConfigurationProperty property = source.getConfigurationProperty(name);
                if (property != null) {
                    return property;
                }
            }
            return null;
        }
    

    构建对象,注入springbean。

        private void registerBeanDefinition(String beanName, Class<?> type,
                MergedAnnotation<ConfigurationProperties> annotation) {
            Assert.state(annotation.isPresent(), () -> "No " + ConfigurationProperties.class.getSimpleName()
                    + " annotation found on  '" + type.getName() + "'.");
            this.registry.registerBeanDefinition(beanName, createBeanDefinition(beanName, type));
        }
    

    相关文章

      网友评论

          本文标题:springboot源码-自动化配置

          本文链接:https://www.haomeiwen.com/subject/rsqogdtx.html