一、SpringBoot的探究
1、POM文件
(1)父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
</parent>
- 它的上级父项目为(SpringBoot的版本号的仲裁中心):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.4</version>
</parent>
注意:
它的上级父项目里面管理着SpringBoot应用里面的所有以来版本;以后我们导入依赖是不需要写版本号(没有再dependencies里面管理的依赖项目自然需要声明版本号)
(2)导入依赖
<!--SpringBoot框架web项目起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- spring-boot-starter-web:
- Spring-boot-starter:是SpringBoot的场景启动器;帮我们导入web模块正常运行所依赖的组件。
- SpringBoot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目里面引入这些starter相关场景的所有的依赖都会导入进来,需要什么依赖就导入什么样场景的启动器即可。
2、主程序类(入口类)
/**
* SpringBoot项目启动入口类
*/
//SpringBoot核心注解,主要用于开启spring自动配置
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//让Spring应用启动起来
SpringApplication.run(Application.class, args);
}
}
表示这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用,Spring Boot会自动扫描@SpringBootApplication所在类的同级包,其注解的源代码如下:
@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 {
SpringBoot的配置类,标注在某个类上,表示这是一个SpringBoot的配置类
配置类上标注这个注解
3、自动配置原理
(1)自动配置原理:
1、SpringBoot启动的时候加载主配置文件,开启了自动配置功能@EnableAutoConfiguration
2、@EnableAutoConfiguration作用:
根据类路径中的 jar 包依赖为当前项目开启自动配置功能,例如,添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC的依赖并会对其进行自动配置,其底层源码如下:
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
- @AutoConfigurationPackage:自动配置包,其底层源码如下:
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
- @Import:Spring底层注解,给容器中导入一个组件,导入组件由Registrar.class决定;
- @Import({AutoConfigurationImportSelector.class}):
导入哪些组件的选择器; 将所有需要导入的组件以全类名的方式返回并添加到容器中去;其会给 容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件,从而免去了手动 编写配置注入功能组件等功能工作。
- AutoConfigurationImportSelector:
- A、可以查看里面的selectImports()方法的内容,并通过
List< String > configurations=getCandidateConfigurations(...)
获取候选的配置类 - B、扫描所有jar包类路径下的META-INF/spring.factories
- C、把扫描到的这些文件的内容包装成properties对象,再从properties对象中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把它们添加到容器中;也就是将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值添加到容器中
- D、每一个这样的xxxAutoConfiguration类都是容器中的每一个组件,都加入到容器中,用它们来做自动配置
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
..........
(3)解释自动配置原理(以HttpEncodingAutoConfiguration:Http编码自动配置为例)
@Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({ServerProperties.class})
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
prefix = "server.servlet.encoding",
value = {"enabled"},
matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
解析各注解的作用:
- @Configuration:表示这是一个配置类,也可以给容器中添加组件
- @EnableConfigurationProperties:启动指定类的ConfigurationProperties功能,将配置文件中对应的值和xxxProperties属性类绑定起来。
@ConfigurationProperties(
prefix = "server",
ignoreUnknownFields = true
)
public class ServerProperties {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
return filter;
}
}
- @ConfigurationProperties:从配置文件中获取指定的值和Bean属性值进行绑定,并把xxxProperties加入到ioc容器中
- @CondittionalOnWebApplication:Spring底层@Condittional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效
- @CondittionalOnClass:判断当前项目是否有这个类,里面的 CharacterEncodingFilter是SpringMVC中进行乱码解决的过滤器
- @ConditionOnProperty:判断配置文件中是否存在某个配置 “spring.http.encoding”;如果不存在,判断也是生效的。
- @Bean:给容器添加组件,这个组件的某些值需要properties中获取,而前面的属性private final HttpEncodingProperties properties;已经和SpringBoot配置文件映射了,而只有一个有参构造方法的情况下,properties参数的值就会从ioc容器中获取出来。
#server.port=8080
#server.servlet.context-path=/
spring.profiles.active= test
#我们能配置的属性是来源于这个功能的properties类
spring.http.encoding.enabled=true
spring.http.encoding.charset=utf-8
spring.http.encoding.force=true
(4)总结
- SpringBoot在启动的时候从类路径下的META-INF/Spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类生效之后,就帮我们进行自动配置工作。
- 根据当前不同的条件,决定这个配置类是否生效,一但这个配置类生效,该配置类就会给容器中添加各种组件。这些组件的属性是从对应的properties类中获取的,而这些properties类里面的每一个属性又是和配置文件绑定的。
- 所有在配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能能对应的这个属性类;
- 需要通过在配置文件中启动debug=true属性,让控制台打印自动配置报告,我们就可以知道哪些自动配置类生效了。
(5)SpringBoot精髓
(1)SpringBoot自动会加载大量的自动配置类:xxxAutoConfiguration
(2)当我们需要的配置类在SpringBoot中没有,这时就要自己配置
(3)当这些配置类生效之后就会给容器中添加各种组件
(4)添加组件的时候,会从xxxProperties类中获取某些属性,我们就可以在配置文件中指定这些属性的值。