SpringBoot_自动配置原理分析

SpringApplication.run()方法底层调用过程

1、在 Spring Boot 的应用程序类的main方法中,调用了SpringApplication类中的run()方法。

package fun.hara.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootApplication {
    public static void main(String [] args){
        SpringApplication.run(BootApplication.class, args); 
        System.out.println("项目已启动...");
    }
}

2、SpringApplication中的run()方法会调用同类中的getSpringFactoriesInstances()方法。

在该方法中调用了SpringFactoriesLoader类中的loadFactoryNames获取工厂名,并完成实例化相关操作。

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
         // 加载工厂名字
        Set<String> names = new LinkedHashSet
            (SpringFactoriesLoader.loadFactoryNames(type, classLoader));    
        // 实例化相关操作
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
}

3、 SpringFactoriesLoadaer类中的loadSpringFactories()方法会去读取spring.properties配置文件。

 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();
                // 其余代码略 ...

Spring.factories配置文件

该配置文件在spring-boot-autoconfigure-2.2.0.RELEASE.jar包的/META-INF/路径下。

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

# ...
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\

# 其余配置略

可以看到,该配置文件中主要是包含了各种类的全限定名。

SolrAutoConfiguration类为例:

package org.springframework.boot.autoconfigure.solr;

// 部分代码略
@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({HttpSolrClient.class, CloudSolrClient.class}) // 类加载的条件
@EnableConfigurationProperties({SolrProperties.class})  // 对于的配置文件
public class SolrAutoConfiguration {
    public SolrAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean
    public SolrClient solrClient(SolrProperties properties) {
        return (SolrClient)(StringUtils.hasText(properties.getZkHost()) ? (new Builder(Arrays.asList(properties.getZkHost()), Optional.empty())).build() : (new org.apache.solr.client.solrj.impl.HttpSolrClient.Builder(properties.getHost())).build());
    }
}

SolrProperties

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.boot.autoconfigure.solr;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(
    prefix = "spring.data.solr"
)
public class SolrProperties {
    private String host = "http://127.0.0.1:8983/solr";
    private String zkHost;

    public SolrProperties() {
    }

    public String getHost() {
        return this.host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getZkHost() {
        return this.zkHost;
    }

    public void setZkHost(String zkHost) {
        this.zkHost = zkHost;
    }
}

可以看到,SolrProperties类包含了Solr相关的默认配置。我们也可在application.propertiesapplication.yml中自定义配置值来覆盖默认的配置。

小结

SpringApplication.run()方法中调用了SpringFactoriesLoader.loadFactoryNames()方法,通过读取spring.factories,得到各种Configuration类的全限定名,在根据每个类的加载条件觉得是否加载该类完成实例化。

另外每个Configuration类通过Properties类中的默认配置完成所支持的技术框架的配置,我们可以通过全局配置文件来修改覆盖默认配置。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容