目录
⚪核心配置文件 META-INF/spring.factories
打开新建的项目的pom.xml:
我们会发现它主要依赖于一个父项目,管理项目的资源过滤及插件

点进去,发现还有一个父依赖

点击进入,这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心
- "1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0modelVersion>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-dependenciesartifactId>
- <version>2.7.3version>
- <packaging>pompackaging>
- <name>spring-boot-dependenciesname>
- <description>Spring Boot Dependenciesdescription>
- <url>https://spring.io/projects/spring-booturl>
- <licenses>
- <license>
- <name>Apache License, Version 2.0name>
- <url>https://www.apache.org/licenses/LICENSE-2.0url>
- license>
- licenses>
- <developers>
- <developer>
- <name>Pivotalname>
- <email>info@pivotal.ioemail>
- <organization>Pivotal Software, Inc.organization>
- <organizationUrl>https://www.spring.ioorganizationUrl>
- developer>
- developers>
- <scm>
- <url>https://github.com/spring-projects/spring-booturl>
- scm>

因此,我们在写或者引入一些SpringBoot依赖的时候,不需要指定版本(因为有这些版本仓库)
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependencies>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-testartifactId>
- <scope>testscope>
- dependency>
- dependencies>
- spring-boot-starter-web:帮助自动导入web环境所有的依赖
- SpringBoot将所有的功能场景都抽取出来,做成一个个的starter (启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来
- 也可以自己自定义 starter;
- //标注该类是一个SpringBoot的应用:启动类下的所有资源被导入
- @SpringBootApplication
- public class HelloworldApplication {
-
- public static void main(String[] args) {
- //将SpringBoot应用启动
- SpringApplication.run(HelloworldApplication.class, args);
- }
- }
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by FernFlower decompiler)
- //
-
-
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @SpringBootConfiguration
- @EnableAutoConfiguration
- //@ComponentScan:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
- @ComponentScan(
- excludeFilters = {@Filter(
- type = FilterType.CUSTOM,
- classes = {TypeExcludeFilter.class}
- ), @Filter(
- type = FilterType.CUSTOM,
- classes = {AutoConfigurationExcludeFilter.class}
- )}
- )
- public @interface SpringBootApplication {
- @AliasFor(
- annotation = EnableAutoConfiguration.class
- )
- Class>[] exclude() default {};
-
- @AliasFor(
- annotation = EnableAutoConfiguration.class
- )
- String[] excludeName() default {};
-
- @AliasFor(
- annotation = ComponentScan.class,
- attribute = "basePackages"
- )
- String[] scanBasePackages() default {};
-
- @AliasFor(
- annotation = ComponentScan.class,
- attribute = "basePackageClasses"
- )
- Class>[] scanBasePackageClasses() default {};
-
- @AliasFor(
- annotation = ComponentScan.class,
- attribute = "nameGenerator"
- )
- Class extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
-
- @AliasFor(
- annotation = Configuration.class
- )
- boolean proxyBeanMethods() default true;
- }
springboot的配置
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Configuration //spring配置类
- @Indexed
- public @interface SpringBootConfiguration {
- @AliasFor(
- annotation = Configuration.class
- )
- boolean proxyBeanMethods() default true;
- }
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Component //说明这也是一个spring组件
- public @interface Configuration {
- @AliasFor(
- annotation = Component.class
- )
- String value() default "";
-
- boolean proxyBeanMethods() default true;
- }
@EnableAutoConfiguration:自动配置,告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @AutoConfigurationPackage //自动配置包
- @Import({AutoConfigurationImportSelector.class}) //自动配置导入选择
- public @interface EnableAutoConfiguration {
- String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
-
- Class>[] exclude() default {};
-
- String[] excludeName() default {};
- }
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @Import({Registrar.class}) //自动配置包注册
- public @interface AutoConfigurationPackage {
- String[] basePackages() default {};
-
- Class>[] basePackageClasses() default {};
- }
- static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
- Registrar() {
- }
- public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
- AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
- }
- public Set
- return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
- }
- }


springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,自动装配就会生效,则配置成功
SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中,将所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;
有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

- //标注该类是一个SpringBoot的应用
- @SpringBootApplication
- public class HelloworldApplication {
-
- public static void main(String[] args) {
- //将SpringBoot应用启动
- //SpringApplication类
- //run方法
- SpringApplication.run(HelloworldApplication.class, args);
- }
- }
构造器:
- public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
- this.sources = new LinkedHashSet();
- this.bannerMode = Mode.CONSOLE;
- this.logStartupInfo = true;
- this.addCommandLineProperties = true;
- this.addConversionService = true;
- this.headless = true;
- this.registerShutdownHook = true;
- this.additionalProfiles = Collections.emptySet();
- this.isCustomEnvironment = false;
- this.lazyInitialization = false;
- this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
- this.applicationStartup = ApplicationStartup.DEFAULT;
- this.resourceLoader = resourceLoader;
- Assert.notNull(primarySources, "PrimarySources must not be null");
- this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
- this.webApplicationType = WebApplicationType.deduceFromClasspath();
- this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
- this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
- this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
- this.mainApplicationClass = this.deduceMainApplicationClass();
- }
- public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
- return run(new Class[]{primarySource}, args);
- }
- public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
- return (new SpringApplication(primarySources)).run(args);
- }
配置文件到底能写什么?怎么写???
SpringBoot官方文档中有大量的配置,我们无法全部记住
⚪以HttpEncodingAutoConfiguration(Http编码自动配置)为例
-
- //表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件;
- @Configuration
-
- //启动指定类的ConfigurationProperties功能;
- //进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;
- //并把HttpProperties加入到ioc容器中
- @EnableConfigurationProperties({HttpProperties.class})
-
- //Spring底层@Conditional注解
- //根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;
- //这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
- @ConditionalOnWebApplication(
- type = Type.SERVLET
- )
-
- //判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
- @ConditionalOnClass({CharacterEncodingFilter.class})
-
- //判断配置文件中是否存在某个配置:spring.http.encoding.enabled;
- //如果不存在,判断也是成立的
- //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
- @ConditionalOnProperty(
- prefix = "spring.http.encoding",
- value = {"enabled"},
- matchIfMissing = true
- )
-
- public class HttpEncodingAutoConfiguration {
- //他已经和SpringBoot的配置文件映射了
- private final Encoding properties;
- //只有一个有参构造器的情况下,参数的值就会从容器中拿
- public HttpEncodingAutoConfiguration(HttpProperties properties) {
- this.properties = properties.getEncoding();
- }
-
- //给容器中添加一个组件,这个组件的某些值需要从properties中获取
- @Bean
- @ConditionalOnMissingBean //判断容器没有这个组件?
- public CharacterEncodingFilter characterEncodingFilter() {
- CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
- filter.setEncoding(this.properties.getCharset().name());
- filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
- filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
- return filter;
- }
- //。。。。。。。
- }
根据当前不同的条件判断,决定这个配置类是否生效!


@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是所有的都生效了。
我们怎么知道哪些自动配置类生效?
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

Positive matches:(自动配置类启用的:正匹配)
Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
Unconditional classes: (没有条件的类)