Springboot自动装配

Springboot自动装配

springboot启动时我们常见的就是一个注解@SpringBootApplication 和 SpringApplication的run方法,前面介绍过run(springboot启动过程),今天详细看一下@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);
}

filter过滤的时候会将spring.factories解析出来的作为候选,在spring-autoconfigure-metadata.properties找它的装配条件,不是所有定义的自动装配类都需要装配。例如:这是要装配的dataSource
springspring.factories里的dataSource
这是它的条件

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.ConditionalOnClass=javax.sql.DataSource,org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType

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

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

@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值