• 关于注解@SpringBootApplication的一些认识


    找到主配置类,点进@SpringBootApplication注解

    下面是@SpringBootApplication注解的主要配置:

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

    重点看看@EnableAutoConfiguration

    点进@EnableAutoConfiguration

    下面是@EnableAutoConfiguration注解的主要配置:

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

    @AutoConfigurationPackage在Hello World中已经说过,让我们点进AutoConfigurationImportSelector类

    点进AutoConfigurationImportSelector类

    • 在AutoConfigurationImportSelector类中有selectImports方法
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    	if (!isEnabled(annotationMetadata)) {
    		return NO_IMPORTS;
    	}
    	AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
    			.loadMetadata(this.beanClassLoader);
    	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
    			annotationMetadata);
    	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    
    • 该方法中调用了getAutoConfigurationEntry方法,点进getAutoConfigurationEntry方法
    protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
    		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 = filter(configurations, autoConfigurationMetadata);
    	fireAutoConfigurationImportEvents(configurations, exclusions);
    	return new AutoConfigurationEntry(configurations, exclusions);
    }
    
    • 发现configurations集合,里面调用了getCandidateConfigurations方法,再点进getCandidateConfigurations方法
    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;
    }
    

    发现调用了SpringFactoriesLoader.loadFactoryNames方法

    点进loadFactoryNames方法

    发现如下代码:

    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
            String factoryTypeName = factoryType.getName();
            return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
        }
    
        private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
            MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
            if (result != null) {
                return result;
            } else {
                try {
                    Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                    LinkedMultiValueMap result = new LinkedMultiValueMap();
    
                    ...
    
                    cache.put(classLoader, result);
                    return result;
                } catch (IOException var13) {
                    throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
                }
            }
        }
    

    可以看到,Spring Boot会扫描所有jar包类路径下META-INF/spring.factories里的内容,并包装成properties对象

    那么factoryTypeName又是什么呢,其实就是传进来的Class<?> factoryType

    查看传入的Class<?> factoryType

    • Class<?> factoryType是由前面的SpringFactoriesLoader.loadFactoryNames传入的
    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;
    }
    
    • 点进getSpringFactoriesLoaderFactoryClass()
    protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    	return EnableAutoConfiguration.class;
    }
    

    可以看到,最终会返回EnableAutoConfiguration.class类名对应的值,即把这些添加到容器中

    打开一个jar包,看看什么样

    点开一个jar包,打开META-INF/spring.factories

    # Auto Configure
    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.cloud.CloudServiceConnectorsAutoConfiguration,
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,
    org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,
    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,
    ...
    

    终于找到了EnableAutoConfiguration对应的值,这样每一个xxxAutoConfiguration就被加载进来了

    接下来,让我们以HttpEncodingAutoConfiguration为例,看看我们在application.properties中究竟能配置哪些属性呢

    点开HttpEncodingAutoConfiguration类

    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(HttpProperties.class)
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @ConditionalOnClass(CharacterEncodingFilter.class)
    @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
    public class HttpEncodingAutoConfiguration {
    

    发现了EnableConfigurationProperties注解,点进HttpProperties去看看

    @ConfigurationProperties(prefix = "spring.http")
    public class HttpProperties {
    

    现在你应该知道如何配置application.properties文件了吧

  • 相关阅读:
    Oracle-DQL 7- 集合操作
    Oracle-DQL 6- 子查询
    Oracle-DQL 5- 分组函数(多行函数)
    Oracle-DQL 4- 多表查询
    Oracle-DQL 3- 单行函数
    构建gulp项目
    重开Vue2.0
    ES6
    emmet简单记录
    webpack 3.X研究
  • 原文地址:https://www.cnblogs.com/renoside/p/13606724.html
Copyright © 2020-2023  润新知