美文网首页springboot2.0
springboot2.0自动注入文件spring.factor

springboot2.0自动注入文件spring.factor

作者: 昨日已逝去 | 来源:发表于2018-12-05 14:37 被阅读317次

    1.首先看下启动类:

    
    @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 {
    
    
    
    

    再进入@EnableAutoConfiguration中查看

    
    @Target(ElementType.TYPE)
    
    @Retention(RetentionPolicy.RUNTIME)
    
    @Documented
    
    @Inherited
    
    @AutoConfigurationPackage
    
    @Import(AutoConfigurationImportSelector.class)
    
    public @interface EnableAutoConfiguration {
    
    

    发现加载了一个AutoConfigurationImportSelector.class

    温馨提示:所有实现ImportSelector的类,都会在启动时被ConfigurationClassParser中的processImports进行实例化,并执行selectImports方法。

    2.查看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 configurations = getCandidateConfigurations(annotationMetadata,
    
            attributes);
    
      configurations = removeDuplicates(configurations);
    
      Set exclusions = getExclusions(annotationMetadata, attributes);
    
      checkExcludedClasses(configurations, exclusions);
    
      configurations.removeAll(exclusions);
    
      configurations = filter(configurations, autoConfigurationMetadata);
    
      fireAutoConfigurationImportEvents(configurations, exclusions);
    
      return StringUtils.toStringArray(configurations);
    
    }
    
    

    通过方法可知是为了选出想要加载的import类,而如何获取这些类呢?其实是通过一个SpringFactoriesLoader去加载对应的spring.factories

    下面展示如何和此类建立关系。

    我们进入selectImports方法中的getCandidateConfigurations

    
    protected ListgetCandidateConfigurations(AnnotationMetadata metadata,
    
          AnnotationAttributes attributes) {
    
    List 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;
    
    }
    

    仔细看SpringFactoriesLoader.loadFactoryNames所需的参数,里面有个getSpringFactoriesLoaderFactoryClass()。下面看下这个方法的返回值是什么?

        protected Class<?> getSpringFactoriesLoaderFactoryClass() {
            return EnableAutoConfiguration.class; //返回的是一个接口
        }
    

    可以看出返回的是一个EnableAutoConfiguration.class,接下来SpringFactoriesLoader会根据这个interface所有spring.factoriesEnableAutoConfiguration.class所对应的values,并返回。

    3. SpringFactoriesLoader如何加载

    此类中只有三个方法,我们使用了其中二个

    • loadFactoryNames
    
    public static ListloadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader) {
    
    String factoryClassName = factoryClass.getName();
    
      return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    
    }
    
    
    • loadSpringFactories
    
    private static Map>loadSpringFactories(@Nullable ClassLoader classLoader) {
    
    MultiValueMap result =cache.get(classLoader);
    
      if (result !=null) {
    
    return result;
    
      }
    
    try {
    
    Enumeration urls = (classLoader !=null ?
    
    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
    
    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    
          result =new LinkedMultiValueMap<>();
    
          while (urls.hasMoreElements()) {
    
    URL url = urls.nextElement();
    
            UrlResource resource =new UrlResource(url);
    
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
    
            for (Map.Entry entry : properties.entrySet()) {
    
    List factoryClassNames = Arrays.asList(
    
    StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
    
                result.addAll((String) entry.getKey(), factoryClassNames);
    
            }
    
    }
    
    cache.put(classLoader, result);
    
          return result;
    
      }
    
    catch (IOException ex) {
    
    throw new IllegalArgumentException("Unable to load factories from location [" +
    
    FACTORIES_RESOURCE_LOCATION +"]", ex);
    
      }
    
    }
    
    

    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :就是去加载对应的文件。

    相关文章

      网友评论

        本文标题:springboot2.0自动注入文件spring.factor

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