• SpringBoot 启动时加载的自动配置类(SpringFactoriesLoader、SPI)


    通过 @SpringBootApplication 注解导入

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {

    通过 @EnableAutoConfiguration 注解

    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {

    org.springframework.boot.autoconfigure.AutoConfigurationImportSelector

    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        // 过滤掉重复的
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        // 删掉排除的
        configurations.removeAll(exclusions);
        // 过滤掉不用配置的
        configurations = getConfigurationClassFilter().filter(configurations);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }

    spring 加载自动配置类依靠的是 SpringFactoriesLoader 类,该类会自动加载 ClassLoader 下所有 jar 包中的 META-INF/spring.factories 文件所配置的 Bean,类似于 JDK 的 SPI 机制

    public final class SpringFactoriesLoader {
    
        public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    
        private static final Log logger = LogFactory.getLog(org.springframework.core.io.support.SpringFactoriesLoader.class);
    
        private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
    
        public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
            Assert.notNull(factoryType, "'factoryType' must not be null");
            ClassLoader classLoaderToUse = classLoader;
            if (classLoaderToUse == null) {
                classLoaderToUse = org.springframework.core.io.support.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());
            for (String factoryImplementationName : factoryImplementationNames) {
                result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
            }
            AnnotationAwareOrderComparator.sort(result);
            return result;
        }
    
        public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
            String factoryTypeName = factoryType.getName();
            return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
        }
    
        private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
            MultiValueMap<String, String> result = cache.get(classLoader);
            if (result != null) {
                return result;
            }
    
            try {
                // 加载文件
                Enumeration<URL> 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()) {
                        String factoryTypeName = ((String) entry.getKey()).trim();
                        for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                            result.add(factoryTypeName, factoryImplementationName.trim());
                        }
                    }
                }
                cache.put(classLoader, result);
                return result;
            }
            catch (IOException ex) {
                throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
            }
        }
    
        @SuppressWarnings("unchecked")
        private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
            try {
                Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
                if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
                    throw new IllegalArgumentException("Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
                }
                return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
            }
            catch (Throwable ex) {
                throw new IllegalArgumentException("Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]", ex);
            }
        }
    }

    spring-boot-autoconfigure 包中的 spring.factories(部分) 文件

    # Initializers
    org.springframework.context.ApplicationContextInitializer=
    org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
    org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
    
    # Application Listeners
    org.springframework.context.ApplicationListener=
    org.springframework.boot.autoconfigure.BackgroundPreinitializer
    
    # Auto Configuration Import Listeners
    org.springframework.boot.autoconfigure.AutoConfigurationImportListener=
    org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
    
    # Auto Configuration Import Filters
    org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=
    org.springframework.boot.autoconfigure.condition.OnBeanCondition,
    org.springframework.boot.autoconfigure.condition.OnClassCondition
    
    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
    
    # Failure analyzers
    org.springframework.boot.diagnostics.FailureAnalyzer=
    org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,
    org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer
    
    # Template availability providers
    org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=
    org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,
    org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider

    获取全部

    获取 EnableAutoConfiguration 对应的


    https://www.cnblogs.com/lifacheng/p/12971628.html

    https://blog.csdn.net/f641385712/article/details/89231174

  • 相关阅读:
    BZOJ 4769: 超级贞鱼 逆序对 + 归并排序
    BZOJ 4897: [Thu Summer Camp2016]成绩单 动态规划
    luogu 4059 [Code+#1]找爸爸 动态规划
    CF718C Sasha and Array 线段树 + 矩阵乘法
    计蒜客 2238 礼物 期望 + 线段树 + 归并
    BZOJ 2157: 旅游 (结构体存变量)
    BZOJ 3786: 星系探索 ETT
    BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
    Spring的几种初始化和销毁方法
    SpringCloud之Zuul高并发情况下接口限流(十二)
  • 原文地址:https://www.cnblogs.com/jhxxb/p/13570269.html
Copyright © 2020-2023  润新知