1.什么是SpringBoot?
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
2.SpringBoot的优点
-
Create stand-alone Spring applications
- 创建独立Spring应用
-
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
- 内嵌web服务器
-
Provide opinionated ‘starter’ dependencies to simplify your build configuration
- 自动starter依赖,简化构建配置
-
Automatically configure Spring and 3rd party libraries whenever possible
- 自动配置Spring以及第三方功能
-
Provide production-ready features such as metrics, health checks, and externalized configuration
- 提供生产级别的监控、健康检查及外部化配置
-
Absolutely no code generation and no requirement for XML configuration
- 无代码生成、无需编写XML
3.SpringBoot快速入门
3.1 环境搭建
- jdk8及以上
- maven 3.3以上
3.2 创建一个maven工程
3.3 引入依赖
<!--引入SpringBoot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
</parent>
<!--web开发所需要的环境-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3.4 编写主程序
/**
* @author Jeremy Li
* @data 2021/1/6 - 15:45
* 主程序类
* @SpringBootApplication:这是一个SpringBoot应用
*/
@SpringBootApplication
public class ApplicationMain {
public static void main(String[] args) {
SpringApplication.run(ApplicationMain.class, args);
}
}
3.5 编写业务
/**
* @author Jeremy Li
* @data 2021/1/6 - 15:51
*/
//@ResponseBody
//@Controller
@RestController
public class HiController {
@RequestMapping("/hi")
public String hello01(){
return "hi, world!!!";
}
}
注意点:
-
springboot项目的入口为主程序文件的main方法,运行main方法即启动maven工程
-
默认情况下,主程序与业务层应该放在同一package下,否则无法在spring容器中找到相应的bean
- SpringBoot中的新注解==@RestController==可以替代@ResponseBody、@Controller
3.6 测试
直接运行主程序文件中的main方法
3.7 简化配置
application.properties
# 可以更改很多配置,如tomcat、
server.port=8888
可以更改很多配置,详细可以在SpringBoot文档中查看
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html
3.8 简化部署
之前的Web项目都是通过打包为war包,然后部署到tomcat服务器上运行
现在可以通过配置一个插件,并在pom.xml中声明打包类型,即可把项目打包成jar包,直接在目标服务器运行即可
pom.xml
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
4.了解自动配置原理
4.1 SpringBoot特点
4.1.1 依赖管理
- 父项目做依赖管理
<!--我们引入的父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
</parent>
<!--我们引入的父项目的父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.1</version>
</parent>
几乎声明了所有开发中所常用的版本号,并且具有自动版本仲裁机制
-
开发导入starter场景启动器
-
官方的有很多
spring-boot-starter-*
, * 就是某种场景 -
只要引入starter,这个场景下几乎所有常规需要的依赖,都会自动引入
-
SpringBoot支持的所有场景
-
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
-
-
第三方提供的简化开发的场景启动器
*-spring-boot-starter
-
所有的场景启动器最底层的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.4.1</version> <scope>compile</scope> </dependency>
-
-
无需写版本号,自动版本仲裁
-
引入非版本仲裁的jar时,要写版本号
-
利用修改依赖的版本号
spring-boot-dependencies中会规定一个当前依赖的版本,可以通过一下操作,实现修改版本号
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
4.1.2 自动配置
-
自动配好Tomcat
- 引入Tomcat依赖
- 配置Tomcat
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.4.1</version> <scope>compile</scope> </dependency>
-
自动配好SpringMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC的常用组件(功能)
-
自动配好Web常见功能,如:DispatherServlet、字符编码问题
-
SpringBoot都已经配好
-
默认包结构
-
默认情况下,主程序与所在包及其子包里面的所有组件都会被自动扫描
-
要想在之外找到相应的:
-
// 放大包的扫描范围 @SpringBootApplication(scanBasePackages = "com.atlige")
-
// 使用以下三个注解代替@SpringBootApplication @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.atlige")
-
-
-
各个配置都有默认值
- 默认配置最终都是映射到MultipartProperties
- 默认配置的值最终会绑定到每个类上,这个类在容器中创建对象
-
按需加载
- 引入了哪些场景,哪些场景的自动配置才会开启
- SpringBoot所有自动配置功能都在
-
…
4.2 容器功能
4.2.1 组件添加
(1)@Configuration
-
基本使用
- 指定某个类为配置类,通过有@Bean注解的方法注册组件
- 不需要将所有的配置都放在一个@Configuration标记的类中,可以通过@Import注释导入额外的配置类
-
Full模式与Lite模式
- 示例
/** * 1、配置类中使用@Bean标注在方法上给容器注册组件,默认也是单实例的 * 2、配置类本身也是组件 * 3、proxyBeanMethods:代理Bean的方法 默认是true * Full (proxyBeanMethods = true):容器中的注册类对象是注册类的代理对象,外部调用组件注册方法始终是单例 * 的,无 * 论外部调用多少次,都会去容器中找 * Lite (proxyBeanMethods = false):容器中的注册类对象本体,外部调用组件注册方法时,每次都会返回新的对象 * @author Jeremy Li * @data 2021/1/6 - 18:33 */ @Configuration public class MyConfig { // 想Ioc容器中添加组件,方法名为组件id,返回类型为组件类型,返回的值就是组件在容器中的实例 /** * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象 * @return */ @Bean("user") public User user(){ return new User("zhangsan", 18); } @Bean public Pet pet(){ return new Pet("Tom"); } }
- 最佳实战
- 配置类组件之间无依赖关系时,用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系时,方法会被调用得到之前单实例组件,用Full模式
(2)@Bean、@Component、@Controller(控制器组件)、@Service(业务逻辑组件)、@Repository(数据库组件)
(3)@ComponentScan、@Import
- 使用@Import(导入到容器中的组件.class):容器中就会自动注册这个组件,id默认是全类名
- 【常用】 可以传入ImportSelector的实现类的class:返回需要导入组件的全类名数组
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// importingClassMetadata可以获得import的注解信息
return new String[]{"com.atlige.boot.bean.Pet", "com.atlige.boot.bean.Black"};
}
}
- ImportBeanDefinitionRegistrar:手动注册bean到容器中
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry 需要注册的类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition1 = registry.containsBeanDefinition("user");
if (definition1){
// 指定Bean定义信息:Bean的类型,Bean的作用域
RootBeanDefinition definition = new RootBeanDefinition(Blue.class);
// 注册一个Bean,指定bean名
registry.registerBeanDefinition("myBlue", definition);
}
boolean definition2 = registry.containsBeanDefinition("com.atlige.boot.bean.Red");
if (definition2){
RootBeanDefinition definition = new RootBeanDefinition(Lol.class);
registry.registerBeanDefinition("myLol", definition);
}
}
}
(4)@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
@Configuration
//@Import({Red.class, User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
@ConditionalOnBean(type = "Pet")
public class MyConfig {
// 想Ioc容器中添加组件,方法名为组件id,返回类型为组件类型,返回的值就是组件在容器中的实例
/**
* 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean("user")
public User user(){
return new User("zhangsan", 18);
}
public Pet pet(){
return new Pet("Tom");
}
}
4.2.2 原生配置文件导入
(1)@ImportResource(“classpath:*”)
导入Spring的配置文件
4.2.3 配置绑定
(1)@ConfigurationProperties
将配置文件中的配置与JavaBean绑定
- @Component + @ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "myhero")
public class Lol {
private String name;
private Integer age;
@Override
public String toString() {
return "Lol{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- 【常用】@EnableConfigurationProperties + @ConfigurationProperties
@EnableConfigurationProperties(Lol.class)
public class MyConfig {
@Bean("user")
public User user(){
return new User("zhangsan", 18);
}
@Bean
public Pet pet(){
return new Pet("Tom");
}
}
=======================JavaBean类=================================
@ConfigurationProperties(prefix = "myhero")
public class Lol {
// 省略
}
4.3 自动配置原理入门
4.3.1 引导加载自动配置类
//@SpringBootApplication // 组合注解
// 等同于下三个
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atlige")
public class ApplicationMain {
public static void main(String[] args){}
}
(1)@SpringBootConfiguration
表明当前类也是一个注解类。
(2)@ComponentScan
表明需要扫描的包
(3)@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
- @AutoConfigurationPackage
自动配置包
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
利用Registrar给容器导入一系列组件,将标注注解的那个类所在的包下(ApplicationMain所在的包)所有组件导入进来
-
@Import(AutoConfigurationImportSelector.class)
- 利用**getAutoConfigurationEntry(annotationMetadata)**给容器中批量导入一些组件
-
// 利用该方法获取到所有需要导入到容器中的候选配置类 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
-
// 利用SpringFactoriesLoader工厂加载得到所有组件 private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader)
-
利用loadSpringFactories从META-INF/spring.factories加载了一个资源文件,默认扫描当前系统里所有
META-INF/spring.factories
位置的文件- spring-boot-autoconfigure-2.4.1.jar包里也有META-INF/spring.factories
- 文件里已经写死了spring-boot一启动,就要给容器中加载的所有配置类
4.3.2 按需开启自动配置项
虽然默认的130个场景在启动时,默认全部加载了,但是最终会根据实际场景按需配置
通过条件装配注解Conditional*系列
4.3.3 修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
// 给容器中加入了文件上传解析器;
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先(@ConditionalOnMissingBean)
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
}
总结:
- SpringBoot先加载所有的自动配置类:xxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会通过@ConfigurationProperties绑定一个配置文件类中的默认值
- 生效的配置类会给容器中装配很多组件
- 只有容器中有的组件,相当于这些功能就已经实现
- 只有用户有自己配置的,就以用户优先
- 定制化配置
- 用户直接用@Bean替换底层的组件
- 用户通过直接在配置文件中设置需要修改的值就可以
xxxAutoConfiguration —>组件—>xxxProperties里面取值—>application.properties
4.4 最佳实践
- 引入场景依赖
- https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
- 查看自动配置了哪些(选做)
- 自己分析,引入场景对应的自动配置一般都生效了
- 配置文件的debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
- 是否需要修改
- 参照文档修改配置项
- https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
- 自己分析。xxxProperties绑定了配置文件的哪些属性
- 自定义加入或替换组件
- @Bean、@Component
- 自定义器xxxCustomizer
- …
- 参照文档修改配置项
4.5 开发小技巧
4.5.1Lombok
4.5.2 dev-tools
ctrl+F9 ---->自动重启
4.5.3 【神器】Spring Initailizr
s://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
- 查看自动配置了哪些(选做)
- 自己分析,引入场景对应的自动配置一般都生效了
- 配置文件的debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
- 是否需要修改
- 参照文档修改配置项
- https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
- 自己分析。xxxProperties绑定了配置文件的哪些属性
- 自定义加入或替换组件
- @Bean、@Component
- 自定义器xxxCustomizer
- …
- 参照文档修改配置项
4.5 开发小技巧
4.5.1Lombok
4.5.2 dev-tools
ctrl+F9 ---->自动重启