2021.7.7 关于 @EnableAotoConfiguration

系列文章目录

例如:day1,2021.7.7 关于 @EnableAotoConfiguration


前言

今天的第二篇

3,@EnableAotoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration

这个就是注解 @EnableAotoConfiguration 的全类名

关于 @EnableAutoConfiguration 大家估计都不陌生,@springbootApplication 下的三大注解之一,

@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 类中,最重要的是 @Import(AutoConfigurationImportSelector.class)

,借助 AutoConfigurationImportSelector@EnableAutoConfiguration 可以帮助springboot 应用将所有符合条件的 @Configuration 配置都加载到当前springboot 创建并使用的IOC容器。

同时,借助于spring框架原有的一个工具类:springFactoriesLoader的支持,@EnableAutoConfiguration 可以智能的自动配置功效才得以大工告成。

在 AutoConfigurationImportSelector 类中可以看到 通过

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
              getBeanClassLoader());

SpringFactoriesLoader.loadFactoryNames()把spring-boot-autoconfigure.jar /MATE-INF/spring.factories 中每一个 xxxAutoConfiguration 文件都加载到容器中,spring.factories 文件里每一个 xxxAutoConfiguration 文件一般都会有下面的条件注解:

  • @ConditionalOnClass : classpath中存在该类时起效
  • @ConditionalOnMissingClass : classpath中不存在该类时起效
  • @ConditionalOnBean : DI容器中存在该类型Bean时起效
  • @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
  • @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
  • @ConditionalOnExpression : SpEL表达式结果为true时
  • @ConditionalOnProperty : 参数设置或者值一致时起效
  • @ConditionalOnResource : 指定的文件存在时起效
  • @ConditionalOnJndi : 指定的JNDI存在时起效
  • @ConditionalOnJava : 指定的Java版本存在时起效
  • @ConditionalOnWebApplication : Web应用环境下起效
  • @ConditionalOnNotWebApplication : 非Web应用环境下起效
...
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\

SpringFactoriesLoader

SpringFactoriesLoader 属于 spring 框架私有的一种扩展方案(类似java的spi方案 java.util.ServiceLoader),其主要功能就是从指定的配置文件MATE-INF/spring-factories 加载配置,spring-factories 时一个典型的java properties 文件。只不过 key 和 value都是 java 类型的完整类名,比如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration
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;
	}

对于 @EnableAutoConfiguration 来说,SpringFactoriesLoader 的用途稍微不同一些,其本意是为了提供 spi 扩展的场景,而在 @EnableAutoConfiguration 场景中,它更多提供了一种配置查找的功能支持,即根据 @EnableAutoConfiguration 的完整类名 org.springframework.boot.autoconfigure.EnableAutoConfiguration

作为查找的key ,获得对应的一组 @Configuration 类。

SpringFactoriesLoader :是一个抽象类,类中定义的静态属性定义了其加载资源的路径:public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";此外还有三个静态方法:

  • loadFactories:加载指定的factoryClass并进行实例化
  • loadFactoryNames:加载指定的factoryClass的名称集合
  • instantiateFactory:对指定的factoryClass进行实例化。

在loadFactories 方法中调用了 loadFactoryNames 以及 instantiateFactory 方法

public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
    
    
        Assert.notNull(factoryType, "'factoryType' must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
    
    
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
        if (logger.isTraceEnabled()) {
    
    
            logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
        }

        List<T> result = new ArrayList(factoryImplementationNames.size());
        Iterator var5 = factoryImplementationNames.iterator();

        while(var5.hasNext()) {
    
    
            String factoryImplementationName = (String)var5.next();
            result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
        }

        AnnotationAwareOrderComparator.sort(result);
        return result;
    }

loadFactories 方法首先获取类加载器,然后调用 loadFactoryNames 方法获取所有指定资源的名称集合 ,接着调用 instantiateFactory 方法实例化这些资源类并将其添加到result集合中,最后调用 AnnotationAwareOrderComparator.sort(result); 方法进行集合的排序。

猜你喜欢

转载自blog.csdn.net/dearand/article/details/118549641