SpringBoot自动配置原理

SpringBoot自动配置

SpringBoot自动配置就是通过注解来对一些常规的配置做了默认配置,简化了各种xml的配置内容。spring boot的自动配置功能,会对我们配置的一些类,自动注入到spring容器中。特别是对于依赖的jar包中的一些类,在我们的工程用到这些类实例时,直接@Autowired或@Resource注解注入使用就可以了

SpringBoot自动配置是如何实现的?

在启动类中可以看到@SpringBootApplication注解,它是SpringBoot的核心注解,也是一个组合注解。这个注解里面又包含了很多其他注解,其中@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan尤为重要。

Springboot是通过@EnableAutoConfiguration注解开启自动配置的,该注解通过对jar包下的spring.factories文件进行扫描,这个文件包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。

 该注解导入了EnableAutoConfigurationImportSelector的selectimports方法

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
   }
   try {
      AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
            .loadMetadata(this.beanClassLoader);
      AnnotationAttributes attributes = getAttributes(annotationMetadata);
      List<String> configurations = getCandidateConfigurations(annotationMetadata,
            attributes);
      configurations = removeDuplicates(configurations);
      configurations = sort(configurations, autoConfigurationMetadata);
      Set<String> exclusions = getExclusions(annotationMetadata, attributes);
      checkExcludedClasses(configurations, exclusions);
      configurations.removeAll(exclusions);
      configurations = filter(configurations, autoConfigurationMetadata);
      fireAutoConfigurationImportEvents(configurations, exclusions);
      return configurations.toArray(new String[configurations.size()]);
   }
   catch (IOException ex) {
      throw new IllegalStateException(ex);
   }
}

通过getCandidateConfiguration方法,获取配置文件列表

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
      AnnotationAttributes attributes) {
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
         getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
   Assert.notEmpty(configurations,
         "No auto configuration classes found in META-INF/spring.factories. If you "
               + "are using a custom packaging, make sure that file is correct.");
   return configurations;
}

loadFactoryNames会加载所有META-INF下有spring.factories文件的jar包,并根据spring.factories文件中的配置,去加载相应的类

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
   String factoryClassName = factoryClass.getName();
   try {
      Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      List<String> result = new ArrayList<String>();
      while (urls.hasMoreElements()) {
         URL url = urls.nextElement();
         Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
         String factoryClassNames = properties.getProperty(factoryClassName);
         result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
      }
      return result;
   }
   catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
            "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

@EnableAutoConfiguration中的@AutoConfigurationPackage和@Import

@import

此注解导入了AutoConfigurationImportSelector类,这个类中有一个很重要的方法——selectImports(),它几乎涵盖了组件自动装配的所有处理逻辑,包括获得候选配置类、配置类去重、排除不需要的配置类、过滤等,最终返回符合条件的自动配置类的全限定名数组。下面源码图中对该方法进行了详尽的注释。

 @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //检查自动配置功能是否开启,默认开启
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        //加载自动配置的元信息
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //获取候选配置类
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        //去掉重复的配置类
        configurations = removeDuplicates(configurations);
        //获得注解中被exclude和excludeName排除的类的集合
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        //检查被排除类是否可实例化、是否被自动注册配置所使用,不符合条件则抛出异常
        checkExcludedClasses(configurations, exclusions);
        //从候选配置类中去除掉被排除的类
        configurations.removeAll(exclusions);
        //过滤
        configurations = filter(configurations, autoConfigurationMetadata);
        //将配置类和排除类通过事件传入到监听器中
        fireAutoConfigurationImportEvents(configurations, exclusions);
        //最终返回符合条件的自动配置类的全限定名数组
        return StringUtils.toStringArray(configurations);
    }

这里需要关注的的是如何得到候选的配置类,可以看到所有的配置信息通过getCandidateConfiguration得到,并最终由一个列表保存。我们继续查看getCandidateConfigurations()方法。

总结:

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值将这些值作为自动配置类导入到容中,自动配置类就生效,帮我们进行自动配置工作;

在这里插入图片描述

我们随便点一个WebMvcAutoConfiguration里面又@Configuration和@Bean对应的注解,所以说springboot自动配置了

在这里插入图片描述 

 

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值