专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Springboot 源码之 如何完成自动装配

从@SpringBootApplication 开始

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
      .......
}

@SpringBootApplication 上的 @EnableAutoConfiguration

从这个注解字面上的意思就是能够自动化配置,springboot很多注解都是以enable开头的,他们的实现都差不多

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ......
}

@import 很重要,就是实现enable相关注解的关键 所以springboot实现自动化装配的第一步就是@import (需要了解 ConfigurationClassPostProcessor 这个类)

@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector#selectImports 方法

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        //这个调用一层套一层,简单的说就是从spring.factories中获得
        //key 为 EnableAutoConfiguration这个注解的全类名,spring会调用
        //本方法,将返回去的类进行解析实例化并且注册到spring容器中
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
                autoConfigurationMetadata, annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

比如说EmbeddedWebServerFactoryCustomizerAutoConfiguration 这个类就会被解析出来

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
...........
}

可以看到上面有个很重要的注解 @EnableConfigurationProperties(ServerProperties.class)

@EnableConfigurationProperties(ServerProperties.class) 这句代码做了什么

//又是import 可见 这个注解多么重要
@Import(EnableConfigurationPropertiesImportSelector.class)
public @interface EnableConfigurationProperties {
    ....
}

EnableConfigurationPropertiesImportSelector 这个类做了什么

    private static final String[] IMPORTS = {
            ConfigurationPropertiesBeanRegistrar.class.getName(),
            ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };

    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
    //返回 ConfigurationPropertiesBeanRegistrar 和 //ConfigurationPropertiesBindingPostProcessorRegistrar 让spring解析注册到spring容器中
        return IMPORTS;
    }

ConfigurationPropertiesBeanRegistrar

    public static class ConfigurationPropertiesBeanRegistrar
            implements ImportBeanDefinitionRegistrar {

        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata,
                BeanDefinitionRegistry registry) {
    //在解析 ConfigurationPropertiesBeanRegistrar 的时候会调用这个方法
    //这个方法干嘛的?
    //会拿到@EnableConfigurationProperties(ServerProperties.class) 注解上的的value,比如这个 ServerProperties 然后注册到 spring容器中,所以ServerProperties就被spring管理起来了
            getTypes(metadata).forEach((type) -> register(registry,
                    (ConfigurableListableBeanFactory) registry, type));
        }
        }

ServerProperties 配置类

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

    /**
     * Server HTTP port.
     */
    private Integer port;

    /**
     * Network address to which the server should bind.
     */
    private InetAddress address;
    .......
    }

这个类很熟悉,就是我们在application.yml 中使用到的,server.prot等等,到了这一步,spring已经把ServerProperties注册成beandefinition,但是什么时候把这个配置类的属性从application.yml中获取到。 还有个类没有说到 ConfigurationPropertiesBindingPostProcessorRegistrar (上文有)

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
            BeanDefinitionRegistry registry) {
    //判断spring中有没有 
    ### ConfigurationPropertiesBindingPostProcessor这个类 
    //如果没有就往 spring注册
    //(这个方法会被反复执行,但是只会注册一次,不知道为啥spring在这边没有优化)
        if (!registry.containsBeanDefinition(
                ConfigurationPropertiesBindingPostProcessor.BEAN_NAME)) {
            registerConfigurationPropertiesBindingPostProcessor(registry);
            registerConfigurationBeanFactoryMetadata(registry);
        }
    }

ConfigurationPropertiesBindingPostProcessor 有什么作用

这就涉及到spring bena的生成 这个类实现了BeanPostProcessor 是spring的一种后置处理器。

//在 bean 实例化之后,初始化之前执行
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        ConfigurationProperties annotation = getAnnotation(bean, beanName,
                ConfigurationProperties.class);
        if (annotation != null) {
        // 执行绑定逻辑,将配置跟bean中的属性绑定,完成自动化装配
            bind(bean, beanName, annotation);
        }
        return bean;
    }

一层套一层…………

文章永久链接:https://tech.souyunku.com/26711

未经允许不得转载:搜云库技术团队 » Springboot 源码之 如何完成自动装配

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们