说明:参考b站雷神springboot2
视频参考
笔记参考
一、基础入门
1、SpringBoot优点
-
创建独立Spring应用
-
内嵌web服务器
以前需要打包war包,放入tomcat才能运行
-
自动starter依赖,简化构建配置
starter启动器,自动依赖
-
自动配置Spring以及第三方功能
-
提供生产级别的监控、健康检查及外部化配置
-
无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
2、SpringBoot缺点
- 人称版本帝,迭代快,需要时刻关注变化
- 封装太深,内部原理复杂,不容易精通
3、时代背景
微服务、分布式、云原生
二、HelloWord
1、版本要求
Maven | 3.5+ |
---|---|
Gradle | 6.8.x, 6.9.x, and 7.x |
2、maven
配置阿里云仓库,下载速度更快
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
3、创建项目
注意idea中配置maven
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<!-- 添加web依赖-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
主函数
package com.mys.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
//业务逻辑
package com.mys.boot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//@ResponseBody //每个方法返回的数据,直接返回给浏览器的数据,而不是跳转
//@Controller
@RestController //包含 @ResponseBody @Controller
public class HelloController {
@RequestMapping("/hello")
public String handle01() {
return "hello";
}
}
Spring Boot统一配置文件:application.properties
server.port=8888
简化部署:安装插件,把项目打成jar包,直接在目标服务器执行即可
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
三、自动配置原理
1、依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
可以修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
2、场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
3、自动配置
- 自动配好tomcat
1.引入tomcat依赖
2.配置tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
-
自动配好SpringMVC
1.引入SpringMVC全套组件
2.自动配好SpringMVC常用组件
-
自动配置好web常见功能,如字符编码
springboot配置好了所有web开发的常见场景
-
默认的包结构
主程序所在的包,及其下面所有子包的组件都会默认扫描,无需配置以前的包扫描
-
想要改变扫描路径,@SpringBootApplication(scanBasePackages=“com.atguigu”)
-
或者**@ComponentScan** 指定扫描路径
@SpringBootApplication 等同于 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.mys.boot")
-
-
各种配置有默认值
-
默认配置最终都是映射到某个类上,如:MultipartProperties
配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
想要改变默认的属性值,在application.properties中修改对应值
-
-
按需加载所有自动配置项
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
4、容器
4.1组件添加
1、@Configuration
Full(proxyBeanMethods = true) 使用场景:组件依赖
Lite(proxyBeanMethods = false)
如果给容器中只是注册组件,别人也不依赖这个组件,选取false,这样可以 加速容器启动
package com.mys.boot.config;
import com.mys.boot.bean.Pet;
import com.mys.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 1.配置类里面使用@Bean标注在方法上给容器注册组件, 默认是单实例
* 2.配置类本身也是组件
* 3.proxyBeanMethods:代理bean的方法
*/
@Configuration(proxyBeanMethods = false)//告诉springboot这是一个配置类 == 配置文件
public class MyConfig {
/**
* 给容器中添加组件,以方法名作为组件id,返回类型是组件类型,返回的值是组件在容器中的实例
* 外部无论对配置类中注册的组件调用多少次,获取的都是容器中之前注册的单实例对象
* @return
*/
@Bean
public User user01() {
User user = new User("zhangshan", 18);
//user组件依赖了pet组件
user.setPet(tomcatPet());
return user;
}
@Bean("tom")//如果不想要方法名作为组件名,可以修改
public Pet tomcatPet() {
return new Pet("tomcat");
}
}
package com.mys.boot;
import com.mys.boot.bean.Pet;
import com.mys.boot.bean.User;
import com.mys.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1.返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2.查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3.容器中注册的组件是单实例的
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:" + (tom01 == tom02));
//4.获取容器中配置类的组件
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//5.配置类调用容器中声明的组件,判断是从容器拿的还是直接调用的方法
//MyConfig代理对象调用方法
//proxyBeanMethods默认true ,表明从容器中拿的是注册的单实例对象
//如果设置proxyBeanMethods=false,从容器中拿到的MyConfig就不是代理对象
User user1 = bean.user01();
User user2 = bean.user01();
System.out.println(user1 == user2);
//6.测试组件依赖关系
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:" + (user01.getPet() == tom));
}
}
@Bean @Component @Controller @Service @Repository @ComponentScan
2、@Import
导入指定类型组件,自动在容器中创建所导入的组件,默认组件的名字是全类名
@Import({User.class, DBHelper.class})
3、Conditional 条件装配
ConditionalOnBean、ConditionalOnMissingBean
4、@ImportResource(“classpath:beans.xml”)导入spring配置文件
4.2 配置绑定
1、@ConfigurationProperties+@Component
package com.mys.boot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component//只有在容器中的组件,才有拥有springboot提供的功能
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
......
}
//application.properties中设置属性值
mycar.brand=BYD
mycar.price=10000
2、@EnableConfigurationProperties
@EnableConfigurationProperties(Car.class)
//1.开启car的配置绑定功能
//2.自动注册car组件到容器中
4.3 原理分析
1、引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
-
@SpringBootConfiguration 代表是springboot
@Configuration 代表当前是一个配置类
-
@ComponentScan 包扫描
-
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
(1)@AutoConfigurationPackage 自动配置包
@Import(AutoConfigurationPackages.Registrar.class)//给容器中导入组件
public @interface AutoConfigurationPackage {}
//利用Register给容器中导入一系列组件
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
//AnnotationMetadata:注解(AutoConfigurationPackage)元信息
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//利用注解元信息获取包名,将包名封装到一个数组中
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
MainApplication 所在包下
(2)@Import(AutoConfigurationImportSelector.class)
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
1.利用getAutoConfigurationEntry(annotationMetadata);
给容器中批量导入一些组件
2.利用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取所有需要导入导入到容器中的组件(127个组件)
3.利用工厂加载得到所有组件
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
4.从META-INF/spring.factories
位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories
位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
2、按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。
xxxxAutoConfiguration 按照条件装配规则(@Conditional),最终会按需配置。
3、修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
//容器中没有这个名字 multipartResolver 的组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
}
总结:
-
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
-
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
-
生效的配置类就会给容器中装配很多组件
-
只要容器中有这些组件,相当于这些功能就有了
-
定制化配置
-
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。application.properties
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
5、最佳实践
-
查看自动配置了哪些
-
- 自己分析,引入场景对应的自动配置一般都生效了
- 配置文件中
debug=true
开启自动配置报告。Negative(不生效)\Positive(生效)
-
是否需要修改
参照文档修改配置项 https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
自己分析。xxxxProperties绑定了配置文件的哪些。
-
自定义加入或者替换组件
-
@Bean、@Component。。。
-
自定义器 XXXXXCustomizer;
四、开发小技巧
1、Lombok
简化JavaBean开发
1.引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2.settings下安装插件
@Data//get set
@ToString//toString
@AllArgsConstructor//有参构造器
@NoArgsConstructor//无参构造器
@EqualsAndHashCode//重写HashCode
2、dev-tools
项目或者页面修改以后:Ctrl+F9;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
3、spring initializr
项目初始化向导
创建项目结构 依赖 主程序类