SpringBoot学习(二)SpringBoot自动装配原理

文章目录

      • 一、自动配置原理
        • 1、pom.xml 分析
        • 2、启动器
        • 3、主程序
      • 二、SpringApplication

一、自动配置原理

1、pom.xml 分析

pom.xml 中存放着大量的jar包依赖,我们在引入SpringBoot依赖的时候,不需要指定版本控制,因为存在这个版本仓库。

SpringBoot学习(二)SpringBoot自动装配原理_第1张图片

2、启动器

  • 像这样的 spring-boot-starter-web依赖 就是通过启动器加载,通过启动器帮我们自动导入web环境的所有依赖
  • 在SpringBoot中将所有的场景,变成了一个个的启动器来执行
  • 我们需要什么场景,就只需要找到对应的启动器即可
    SpringBoot学习(二)SpringBoot自动装配原理_第2张图片

3、主程序

默认的主启动类:

package com.zyh;

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

//标注了这个类是SpringBoot的应用
@SpringBootApplication
public class Spring01HelloworldApplication {

    public static void main(String[] args) {
        //启动了一个服务
        SpringApplication.run(Spring01HelloworldApplication.class, args);
    }

}

点进@SpringBootApplication注解,其中三个重要的注解

@SpringBootConfiguration 
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  • @ComponentScan:扫描并加载符合条件的组件或者bean,将这个bean注入到IOC容器中
  • @SpringBootConfiguration:SpringBoot的配置注解,标注在类上,表示这个类是SpringBoot的配置类
  • @EnableAutoConfiguration:开启自动配置注解,以前需要我们手动配置的,现在SpringBoot就帮我们进行自动配置,点进这个注解继续看:
@AutoConfigurationPackage
@Import(AutoCon.class)
  • @AutoConfigurationPackage :自动配置包
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage { 
} 
  • @Import(AutoConfigurationImportSelector.class):给容器导入组件,自动配置导入选择器。

@Import(AutoConfigurationImportSelector.class) 的源码分析:

  1. 类中的getCandidateConfigurations()方法获取到候选的配置
//获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
            getBeanClassLoader());//getSpringFactoriesLoaderFactoryClass() 返回最开始启动导入自动配置的配置类
    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;
}
  1. getCandidateConfigurations()调用SpringFactoriesLoader的静态方法loadFactoryNames

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    String factoryTypeName = factoryType.getName();
    //调用了loadSpringFactories方法
    return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
  1. 点击查看loadSpringFactories方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    //返回被@EnableAutoConfiguration标注的类
    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<>();
        //将读取到的资源封装成properties
        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);
    }
}
  1. 我们发现多次出现的文件资源:FACTORIES_RESOURCE_LOCATION,点进去查看:
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

打开这个文件:它的位置在我们项目jar包中;
SpringBoot学习(二)SpringBoot自动装配原理_第3张图片
自动配置的根源就在这里
SpringBoot学习(二)SpringBoot自动装配原理_第4张图片
SpringBoot的所有自动配置都是在启动的时候扫描并加载,所有的自动配置都在spring.factories中存放,但是只有判断条件成立,只要导入了对应的starter启动器,自动配置才会生效。
小结:

  • SpringBoot启动的时候,从类路径下/META-INF/spring.factories获取指定的值。
  • 将这些自动装配的类导入IOC容器,自动配置就会生效,以前我们需要手动进行配置的东西,在SpringBoot中它会帮我们进行自动配置。
  • 它会把所有需要导入的组件以类名的方式返回,这些组件就会被添加到容器中。

二、SpringApplication

这个类是我们在创建SpringBoot项目的时候,SpringBoot帮我们自动生成的。
它的作用是为我们开启一个服务

package com.zyh;

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

@SpringBootApplication
public class HangSpringApplication {
    public static void main(String[] args) {
        SpringApplication.run(HangSpringApplication.class, args);
    }
}

SpringApplication的作用:

  • 推断项目是普通项目还是Web项目
  • 查找并加载所有的可用的初始化器,设置到 initializers 属性中
  • 推断出所有的程序应用监听器,设置到initializers属性中
  • 推断并设置main方法的定义类,找到运行的主类

你可能感兴趣的:(SpringBoot)