成都网站建设:,教育类网站怎么做优化,网站自行备案,青海休闲网站建设公司声明原文出处#xff1a;狂神说 文章目录1. pom.xml1 . 父依赖2 . 启动器 spring-boot-starter2. 主启动类的注解1. 默认的主启动类2. SpringBootApplication3. ComponentScan4. SpringBootConfiguration5. SpringBootApplication 注解6. spring.factories7. 结论8. 简单图解3…声明原文出处狂神说 文章目录1. pom.xml1 . 父依赖2 . 启动器 spring-boot-starter2. 主启动类的注解1. 默认的主启动类2. SpringBootApplication3. ComponentScan4. SpringBootConfiguration5. SpringBootApplication 注解6. spring.factories7. 结论8. 简单图解3. 主启动类的方法1. SpringApplication2. run方法流程分析
1. pom.xml
1 . 父依赖
其中它主要是依赖一个父项目主要是管理项目的资源过滤及插件
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.2.5.RELEASE/versionrelativePath/ !-- lookup parent from repository --
/parent
点进去发现还有一个父依赖
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.2.5.RELEASE/versionrelativePath../../spring-boot-dependencies/relativePath
/parent
这里才是真正管理SpringBoot应用里面所有依赖版本的地方SpringBoot的版本控制中心
以后我们导入依赖默认是不需要写版本但是如果导入的包没有在依赖中管理着就需要手动配置版本了
2 . 启动器 spring-boot-starter dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-xxx/artifactId
/dependency
springboot-boot-starter-xxx就是spring-boot的场景启动器
比如 : spring-boot-starter-web帮我们导入了web模块正常运行所依赖的组件
SpringBoot将所有的功能场景都抽取出来做成一个个的starter 启动器只需要在项目中引入这些starter即可所有相关的依赖都会导入进来 要用什么功能就导入什么样的场景启动器即可
2. 主启动类的注解
1. 默认的主启动类
//SpringBootApplication 来标注一个主程序类
//说明这是一个Spring Boot应用
SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {//以为是启动了一个方法没想到启动了一个服务SpringApplication.run(SpringbootApplication.class, args);}
}
2. SpringBootApplication
作用 标注在某个类上说明这个类是SpringBoot的主配置类 SpringBoot就应该运行这个类的main方法来启动SpringBoot应用
进入这个注解
SpringBootConfiguration
EnableAutoConfiguration
ComponentScan(excludeFilters {Filter(type FilterType.CUSTOM,classes {TypeExcludeFilter.class}
), Filter(type FilterType.CUSTOM,classes {AutoConfigurationExcludeFilter.class}
)}
)
……
3. ComponentScan 这个注解在Spring中很重要 ,它对应XML配置中的元素。 作用 自动扫描并加载符合条件的组件或者bean 将这个bean定义加载到IOC容器中
4. SpringBootConfiguration
作用 SpringBoot的配置类 标注在某个类上 表示这是一个SpringBoot的配置类
进入这个注解
// 点进去得到下面的 Component
Configuration
public interface SpringBootConfiguration {}Component
public interface Configuration {} Configuration 说明这是一个配置类 配置类就是对应Spring的xml 配置文件 Component 说明启动类本身也是Spring中的一个组件而已负责启动应用
5. SpringBootApplication 注解
EnableAutoConfiguration 作用 开启自动配置功能 该注解告诉SpringBoot开启自动配置功能这样自动配置才能生效 以前我们需要自己配置的东西而现在SpringBoot可以自动帮我们配置 进入该注解 Inherited
AutoConfigurationPackage
Import({AutoConfigurationImportSelector.class})
public interface EnableAutoConfiguration {
AutoConfigurationPackage
作用 自动配置包
import
作用Spring底层注解import 给容器中导入一个组件
Import({Registrar.class})*
作用将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器
Import({AutoConfigurationImportSelector.class})
作用 给容器导入组件AutoConfigurationImportSelector 自动配置导入选择器 进入AutoConfigurationImportSelector 这个类中有一个这样的方法 // 获得候选的配置
protected ListString getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {//这里的getSpringFactoriesLoaderFactoryClass方法//返回的就是我们最开始看的启动自动导入配置文件的注解类EnableAutoConfigurationListString configurations SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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 类的静态方法我们进入SpringFactoriesLoader类loadFactoryNames() 方法 public static ListString loadFactoryNames(Class? factoryClass, Nullable ClassLoader classLoader) {String factoryClassName factoryClass.getName();//这里它又调用了 loadSpringFactories 方法return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
} 我们继续点击查看 loadSpringFactories 方法 private static MapString, ListString loadSpringFactories(Nullable ClassLoader classLoader) {//获得classLoader 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身MultiValueMapString, String result (MultiValueMap)cache.get(classLoader);if (result ! null) {return result;} else {try {//去获取一个资源 META-INF/spring.factoriesEnumerationURL urls classLoader ! null ? classLoader.getResources(META-INF/spring.factories) : ClassLoader.getSystemResources(META-INF/spring.factories);LinkedMultiValueMap result new LinkedMultiValueMap();//将读取到的资源遍历封装成为一个Propertieswhile(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 factoryClassName ((String)entry.getKey()).trim();String[] var9 StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 var9.length;for(int var11 0; var11 var10; var11) {String factoryName var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException(Unable to load factories from location [META-INF/spring.factories], var13);}}
}发现一个多次出现的文件spring.factories
6. spring.factories
打开spring.factories 看到了很多自动配置的文件这就是自动配置根源所在
7. 结论
SpringBoot 所有的自动配置都是在启动的时候扫描并加载的自动配置真正实现 从classpath中搜寻所有的META-INF/spring.factories配置文件并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项通过反射实例化为对应标注了 Configuration的JavaConfig形式的IOC容器配置类然后将这些都汇总成为一个实例并加载到IOC容器中不过有部分配置类不会一开始就自动加载只有满足 ConditionalOnXXX(xxxx) 中的条件才会生效 —— 导入对应的 start 启动器
8. 简单图解 3. 主启动类的方法
在主启动类的 main 方法中调用这样一个方法 SpringApplication.runSpringApplication.run 方法主要分两部分 一部分是SpringApplication的实例化二是run方法的执行
1. SpringApplication
这个类主要做了以下四件事情 推断应用的类型是普通的项目还是Web项目查找并加载所有可用初始化器 设置到initializers属性中找出所有的应用程序监听器设置到listeners属性中推断并设置main方法的定义类找到运行的主类
查看构造器 public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {// ......this.webApplicationType WebApplicationType.deduceFromClasspath();this.setInitializers(this.getSpringFactoriesInstances();this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass this.deduceMainApplicationClass();
}
2. run方法流程分析