spring-boot-learning自动配置原理

 

 

启动器:

spring-boot-starter:spring-boot场景启动器,帮我们倒入我们场景需要的组件依赖

 不同的场景有不同的启动器:

spring-boot-starter-web       主程序类,主入口类:  
@SpringBootApplication
public class DoneApplication {

    public static void main(String[] args) {
        SpringApplication.run(DoneApplication.class, args);
    }
}
@SpringBootApplication:    Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,
SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;

 

这个注解的详如下:

 

@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 {
@SpringBootConfiguration  springboot的配置类的注解,标注在某个类上,表示这是一个Spring Boot的配置类
@EnableAutoConfiguration  开启自动配置,告诉SpringBoot开启自动配置功能,详解如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {

@Import(Registrar.class):

Spring的底层注解@Import,给容器中导入一个组件;导入的组件由 Registrar.class;

将主配置类(@SpringBootApplication: 标注的类)的所在包及下面所有子包里面的所有组件扫描到容器

 

 

 AutoConfigurationImportSelector 类的作用就是往 Spring 容器中导入组件,导入哪些组件的选择器

将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件, 并配置好这些组件;

 

 


流程;


@SpringbootApplication注解--@EnableAutoConfiguration--@Import(AutoConfigurationImportSelector.class)重要就是这个类

AutoConfigurationImportSelector这个类有个方法:

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

AutoConfigurationImportSelector 的 selectImports 就是用来返回需要导入的组件的全类名数组的

就是通过方法getAutoConfigurationEntry方法

spring-boot-learning自动配置原理
getCandidateConfigurations方法里面

 spring-boot-learning自动配置原理

SpringFactoriesLoader里面函数loadFactoryNames
spring-boot-learning自动配置原理

 

 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();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryImplementationName = var9[var11];
                            result.add(factoryTypeName, factoryImplementationName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }

1111获取配置文件信息:

 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

2222通过函数loadSpringFactories获取一个map集合:

private static Map<String, List<String>> loadSpringFactories

先寻找传入了什么

spring-boot-learning自动配置原理

 

 回到选择器:

spring-boot-learning自动配置原理

 

 333从返回的 Map 中通过刚才传入的 EnableAutoConfiguration.class 参数,获取该 key 下的所有值。

 

spring-boot-learning自动配置原理

 

 

 

 
                   
上一篇:JVM类的加载器及加载过程


下一篇:类的加载与ClassLoader理解