美文网首页
Springboot自动装配

Springboot自动装配

作者: 小软_GCX | 来源:发表于2020-06-15 19:21 被阅读0次

    Springboot自动装配

    springboot启动时我们常见的就是一个注解@SpringBootApplication 和 SpringApplication的run方法,前面介绍过run(https://www.jianshu.com/p/90ebeec86f64),今天详细看一下@SpringBootApplication。

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }
    

    @SpringBootApplication是一个注解的组合,进去看下它里面

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
          @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
          @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    

    主要包含@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan

    首先@ComponentScan,默认扫描的是与该类同级的类或者同级包下的所有类

    其次@SpringBootConfiguration,只是封装了@Configuration,把启动类指定为一个javaConfig(会在容器刷新中的invokeBeanFactoryPostProcessors里进行解析执行)

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    public @interface SpringBootConfiguration {
    
    }
    

    最后@EnableAutoConfiguration

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    
       String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
       /**
        * Exclude specific auto-configuration classes such that they will never be applied.
        * @return the classes to exclude
        */
       Class<?>[] exclude() default {};
    
       /**
        * Exclude specific auto-configuration class names such that they will never be
        * applied.
        * @return the class names to exclude
        * @since 1.3.0
        */
       String[] excludeName() default {};
    
    }
    

    @EnableAutoConfiguration里面有两个主要的注解@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)。

    @AutoConfigurationPackage,该注解的作用是添加该注解的类所在的package(启动类所在路径) 作为 自动配置package 进行管理。

    @Import(AutoConfigurationImportSelector.class),看一下后面它注册到容器中的bean AutoConfigurationImportSelector.class。

    public class AutoConfigurationImportSelector
          implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
          BeanFactoryAware, EnvironmentAware, Ordered {
            //省略。。。。。
    

    其中DeferredImportSelector extends ImportSelector,所以会执行到selectImports,DeferredImportSelector 和 ImportSelector的区别在于DeferredImportSelector为延时加载,等configure都加载完了才开始加载

    看一下AutoConfigurationImportSelector里的selectImports

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
      //判断是否需要自动装配
       if (!isEnabled(annotationMetadata)) {
          return NO_IMPORTS;
       }
      //从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性
       AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
             .loadMetadata(this.beanClassLoader);
       AnnotationAttributes attributes = getAttributes(annotationMetadata);
      //读取META-INF/spring.factories下的EnableAutoConfiguration的配置(这里用到了SpringFactoriesLoader,和启动过程中加载spring.factories中的初始化器和监听器是同一个)
       List<String> configurations = getCandidateConfigurations(annotationMetadata,
             attributes);
      //排除与过滤
       configurations = removeDuplicates(configurations);
       Set<String> exclusions = getExclusions(annotationMetadata, attributes);
       checkExcludedClasses(configurations, exclusions);
       configurations.removeAll(exclusions);
       configurations = filter(configurations, autoConfigurationMetadata);
      //让所有配置在META-INF/spring.factories下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件
       fireAutoConfigurationImportEvents(configurations, exclusions);
       return StringUtils.toStringArray(configurations);
    }
    

    上面这些过程只是确定了需要自定装配的类,真正开始处理是在容器刷新中的invokeBeanFactoryPostProcessors方法里,里面用了ConfigurationClassPostProcessor这个后置处理来处理并且用相应的解析器来解析@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理),具体可参考https://www.jianshu.com/p/ab0b7df24c01

    另外,每个需要自动装配的类都可以根据条件判断是否进行装配@ConditionalXXX,举例mq

    @Configuration
    @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
    @EnableConfigurationProperties(RabbitProperties.class)
    @Import(RabbitAnnotationDrivenConfiguration.class)
    public class RabbitAutoConfiguration {
    

    相关文章

      网友评论

          本文标题:Springboot自动装配

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