在pom文件中java
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
在它的父工程中,有他的核心依赖web
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.1.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
点进去,咱们发现,springboot自动帮咱们管理了依赖spring
这只是其中的一小部分,咱们在写或者引入有一些依赖的时候,不须要指定版本springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
springboot-boot-starter:就是spring-boot的场景启动器app
这里的 spring-boot-starter-web 帮咱们导入了web模块正常运行所依赖的组件;spring-boot
SpringBoot将全部的功能场景都抽取出来,作成一个个的starter (启动器),只须要在项目中引入这些starter便可,全部相关的依赖都会导入进来 , 咱们要用什么功能就导入什么样的场景启动器便可 ;spa
package com.bao; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Springboot01HelloworldApplication { public static void main(String[] args) { SpringApplication.run(Springboot01HelloworldApplication.class, args); } }
@SpringBootApplication 来标注一个主程序类 , 说明这是一个Spring Boot应用命令行
run方法: 将Spring应用启动起来code
咱们看一下@SpringBootApplication
注解xml
//四个标准注解 @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的配置类 ,标注在某个类上,表示这是一个SpringBoot的配置类
- @EnableAutoConfiguration : 启用自动配置,这个注解是让Spring Boot配置可以如此简化的关键性注解
- @ComponentScan : 扫描当前主启动类同级的包
点击@SpringBootConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }
@Configuration : 表明是一个spring配置类
点击
Configuration
发现有一个@Component,表明是一个spring组件
点击@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; }
主要是 :
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)两个
AutoConfigurationPackage(自动配置包)
注解的做用是将 添加该注解的类所在的package 做为 自动配置package 进行管理。
主要是Registrar.class
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited //导入选择器 @Import(AutoConfigurationPackages(自动配置注册包).Registrar.class) public @interface AutoConfigurationPackage { }
@import :Spring底层注解@import , 给容器中导入一个组件 ,导入的组件由 {Registrar.class} 将主配置类 【即@SpringBootApplication标注的类】的所在包及包下面全部子包里面的全部组件扫描到Spring容器 ;
@Import(AutoConfigurationImportSelector.class)
它将全部须要导入的组件以全类名的方式返回 , 这些组件就会被添加到容器中 ;
它会给容器中导入很是多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景须要的全部组件 , 并配置好这些组件 ;
有了自动配置类 , 免去了咱们手动编写配置注入功能组件等的工做;
点击AutoConfigurationImportSelector
有这样的一个方法
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); }
其中 getCandidateConfigurations:获取候选配置
//获取全部配置 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
点击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; }
//返回用来加载配置候选的类。标注了EnableAutoConfiguration注解的类(主启动类) protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
而在
@SpringBootApplication
注解中标注了@EnableAutoConfiguration因此就是启动类下的全部资源被导入
在这里咱们发现了META-INF/spring.factories文件.这个就是自动配置的核心文件
咱们去springboot的jar中寻找该文件
List<String> configurations = SpringFactoriesLoader.loadFactoryNames (getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
点击loadFactoryNames
方法
loadFactoryNames : 获取全部的加载配置
返回的loadSpringFactories
从这些资源中便利了全部的nextElement元素(也能够理解为自动配置)
遍历完成后封装成Properties,供咱们使用
//全部资源加载到配置类中 Properties properties = PropertiesLoaderUtils.loadProperties(resource);
获取项目资源:classLoader.getResources(FACTORIES_RESOURCE_LOCATION) 获取系统资源:ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION))
点击FACTORIES_RESOURCE_LOCATION
,获取静态资源的位置
从META-INF/spring.factories获取配置文件
须要导入对应的starter才能起做用
例如
因为@ConditionalOnClass
的存在,会判断条件成立,才会加载配置这个类
@ConditionalOnXXX
若是这里面的条件都知足,才会生效
SpringBoot全部的自动配置都在启动类中扫描并加载,也就是spring.factories
文件
全部的自动配置类都在这个文件中,可是并不必定生效,要判断条件是否成立,只要导入对应的start,就会有对应的启动器,有了启动器,自动装配就会生效,而后就配置成功了
1.springboot在启动的时候,会从类路径下META-INF/spring.factories
文件中获取指定的值
2.将这些自动配置的类导入容器,自动配置类就会生效,帮咱们进行自动配置
3.springboot帮咱们作了咱们之前须要的配置.
4.整个J2EE的总体解决方案和自动配置都在springboot-autoconfigure的jar包中;
5.他会把全部须要导入的组件,以类名的方式返回,这些组件就会被添加到容器
6.容器中也会存在很是多的XxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景所须要的全部组件
7.有了自动配置类,就不须要写配置文件
咱们找一个打开看看 : WebMvcAutoConfiguration
因此,真正实现是从classpath中搜寻全部的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项经过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 而后将这些都汇总成为一个实例并加载到IOC容器中。
@SpringBootApplication public class SpringbootDemo02Application { public static void main(String[] args) { //该方法返回一个ConfigurableApplicationContext对象 //参数一:应用入口的类 参数类:命令行参数 SpringApplication.run(SpringbootDemo02Application.class, args); } }
分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;
1.推断应用的类型是普通的项目仍是Web项目
2.查找并加载全部可用初始化器 , 设置到initializers属性中
3.找出全部的应用程序监听器,设置到listeners属性中
4.推断并设置main方法的定义类,找到运行的主类