SpringBoot基础
一、SpringBoot简介
1.入门案例
- SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
- 原生开SpringMVC程序过程
1.1入门案例开发步骤
手动创建方式:
①:新建maven项目
②:引入依赖
③:创建引导类
③:开发控制器类
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping("/{id}")
public String getById(@PathVariable Integer id) {
System.out.println("id ==> " + id);
return "hello , spring boot! ";
}
}
④:运行自动生成的Application类
SpringBoot脚手架方式:
①:创建新模块,选择Spring初始化,并配置模块相关基础信息
②:选择当前模块需要使用的技术集
③:开发控制器类
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping("/{id}")
public String getById(@PathVariable Integer id) {
System.out.println("id ==> " + id);
return "hello , spring boot! ";
}
}
④:运行自动生成的Application类
- 最简SpringBoot程序所包含的基础文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<groupId>com.itheima</groupId>
<artifactId>springboot-01-quickstart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- Spring程序与SpringBoot程序对比
注意事项:
基于idea开发SpringBoot程序需要确保联网且能够加载到程序框架结构
1.2基于SpringBoot官网创建项目
1.3SpringBoot项目快速启动
- 对SpringBoot项目打包(执行Maven构建指令Package)
- 执行启动指令
java -jar springboot_01_quickstart.jar //项目的名称根据实际情况修改
注意事项:
jar支持命令行启动需要依赖maven插件支持,请确认打包时是否具有SpringBoot对应的maven插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.SpringBoot概述
问题:
- 入门案例中没有引入spring-webmvc等依赖包,没有配置Tomcat服务器,为什么能正常启动
- 没有配置端口号,为什么是8080端口?
2.1起步依赖
- starter
- SpringBoot中常见项目名称,定义了当前项目使用的所有项目坐标,以达到减少依赖配置的目的
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<groupId>com.itheima</groupId>
<artifactId>springboot-01-quickstart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
<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.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.0</version>
<packaging>pom</packaging>
<properties>
<servlet-api.version>4.0.1</servlet-api.version>
...
</properties>
</project>
- parent
- 所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
- spring-boot-starter-parent(2.5.0)与 spring-boot-starter-parent(2.4.6)共计57处坐标版本不同
<?xml version="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.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.0</version>
</parent>
<artifactId>spring-boot-starter-parent</artifactId>
<packaging>pom</packaging>
...
</project>
- 实际开发
- 使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供
- 如发生坐标错误,再指定version(要小心版本冲突)
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet-api.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet-api.version}</version>
</dependency>
2.2默认配置
tomcat默认配置了端口号为8080
二、基础配置
1.配置文件格式
问题:框架常见的配置文件有哪几种形式?
1.1修改服务器端口
http://localhost:8080/books/1 >>> http://localhost/books/1
SpringBoot提供了多种属性配置方式
- application.properties
server.port=80
- application.yml
server:
port: 81
- application.yaml
server:
port: 82
1.2 自动提示功能消失解决方案
操作步骤:
1.3SpringBoot配置文件加载顺序
application.properties > application.yml > application.yaml
注意事项:
- SpringBoot核心配置文件名为application
- SpringBoot内置属性过多,且所有属性集中在一起修改,在使用时,通过提示键+关键字修改属性
2.yaml
问题:什么是yaml,和properties有什么区别?
- YAML(YAML Ain’t Markup Language),一种数据序列化格式
- 优点:
- 容易阅读
- 容易与脚本语言交互
- 以数据为核心,重数据请格式
- YAML文件扩展名
- .yml(主流)
- .yaml
2.1yaml语法规则
- 大小写敏感
- 属性层级关系使用多行描述,每行结尾使用冒号结束
- 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
- 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
- 表示注释
- 核心规则:数据前面要加空格与冒号隔开
2.2yaml数组数据
- 数组数据在数据书写位置的下方使用减号作为数据开始符合,每行书写一个数据,减号与数据间空格分隔
2.3yaml数据读取
- 使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名}…
- 封装全部数据到Enviornment对象
- 自定义对象封装指定数据【常用】
public class Enterprise {
private String name;
private Integer age;
private String tel;
private String[] subject;
//自行添加getter、setter、toString()等方法
}
- 自定义对象封装数据警告解决方案
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
3.多环境开发配置
问题:在实际开发中,项目的开发环境、测试环境、生产环境的配置信息是否会一致?如何快速切换?
3.1多环境启动配置
- yaml文件多环境启动
- properties文件多环境启动
#主启动配置文件 application.properties
spring.profiles.active=pro
#环境分类配置文件 application-pro.properties
server.port=80
#环境分类配置文件 application-dev.properties
server.port=81
#环境分类配置文件application-test.properties
server.port=82
3.2 多环境启动命令格式
- 带参数启动SpringBoot
java –jar springboot.jar --spring.profiles.active=test
java –jar springboot.jar --server.port=88
java –jar springboot.jar --server.port=88 --spring.profiles.active=test
- 参数加载优先顺序
3.3多环境开发控制
Maven与SpringBoot多环境兼容(步骤)
①:Maven中设置多环境属性
<profiles>
<profile>
<id>dev_env</id>
<properties>
<profile.active>dev</profile.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>pro_env</id>
<properties>
<profile.active>pro</profile.active>
</properties>
</profile>
<profile>
<id>test_env</id>
<properties>
<profile.active>test</profile.active>
</properties>
</profile>
</profiles>
②:SpringBoot中引用Maven属性
③:执行Maven打包指令
- Maven指令执行完毕后,生成了对应的包,其中类参与编译,但是配置文件并没有编译,而是复制到包中
- 解决思路:对于源码中非java类的操作要求加载Maven对应的属性,解析${}占位符
④:对资源文件开启对默认占位符的解析
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>utf-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
- Maven打包加载到属性,打包顺利通过
4.配置文件分类
问题:SpringBoot的配置文件可以放在项目的哪些地方
java –jar springboot.jar --spring.profiles.active=test --server.port=85 --server.servlet.context-path=/heima --server.tomcat.connection-timeout=-1 ... ...
SpringBoot中4级配置文件
1级: file :config/application.yml 【最高】
2级: file :application.yml
3级:classpath:config/application.yml
4级:classpath:application.yml 【最低】
作用:
1级与2级留做系统打包后设置通用属性
3级与4级用于系统开发阶段设置通用属性
三、整合第三方技术
1.整合JUnit
1.1Spring整合Junit(复习)
1.2SpringBoot整合JUnit
【第一步】添加整合junit起步依赖(可以直接勾选)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
【第二步】编写测试类,默认自动生成了一个
@SpringBootTest
class Springboot07JunitApplicationTests {
@Autowired
private BookService bookService;
@Test
public void testSave() {
bookService.save();
}
}
2. 基于SpringBoot实现SSM整合
2.1 Spring整合MyBatis(复习)
- SpringConfig
- 导入JdbcConfig
- 导入MyBatisConfig
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
public class SpringConfig {
}
- JDBCConfig
- 定义数据源(加载properties配置项:driver、url、username、password)
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=itheima
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource getDataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
- MyBatisConfig
- 定义SqlSessionFactoryBean
- 定义映射配置
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.itheima.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.itheima.dao");
return msc;
}
2.2 SpringBoot整合MyBatis
- SpringBoot整合Spring(不存在)
- SpringBoot整合SpringMVC(不存在)
- SpringBoot整合MyBatis(主要)
①:创建新模块,选择Spring初始化,并配置模块相关基础信息
②:选择当前模块需要使用的技术集(MyBatis、MySQL)
③:设置数据源参数
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
注意事项:
- SpringBoot版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url连接串中配置时区,或在MySQL数据库端配置时区解决此问题
jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
④:定义数据层接口与映射配置
@Mapper
public interface UserDao {
@Select("select * from tbl_book where id=#{id}")
Book getById(Integer id);
}
⑤:测试类中注入dao接口,测试功能
@SpringBootTest
class Springboot08MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
public void testGetById() {
Book book = bookDao.getById(1);
System.out.println(book);
}
}
2.3 案例-SpringBoot实现ssm整合
【第一步】创建SpringBoot工程,添加druid依赖
<!-- todo 1 添加druid连接池依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
【第二步】复制springmvc_ssm各种资源(主java类、页面、测试类)
【第三步】删除config包中的所有配置,在BookDao接口上加@Mapper注解
//todo 3 在BookDao接口上加@Mapper注解,让SpringBoot给接口创建代理对象
@Mapper
public interface BookDao {
//...
}
【第四步】将application.properties修改成application.yml,配置端口号和连接参数
server:
port: 80
# todo 4 配置数据库连接参数
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
【第五步】修改BookServiceTest配置类,进行配置
// todo 5 修改单元测试类,添加@SpringBootTest主键,修复@Test注解导包
@SpringBootTest
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById(){
Book book = bookService.getById(2); //传递参数1会抛出异常
System.out.println(book);
}
@Test
public void testGetAll(){
List<Book> all = bookService.getAll();
System.out.println(all);
}
}
【第六步】在static目录中提供index.html页面,跳转到"pages/books.html"
<script>
location.href="pages/books.html"
</script>
最后:运行引导类即可访问
SpringBoot高级
一、SpringBoot自动化配置原理
1.SpringBoot高级-starter依赖管理机制
目的:通过依赖能了解SpringBoot管理了哪些starter
1.通过依赖 spring-boot-dependencies搜索starter-发现非常多的官方starter,并且已经帮助我们管理好了版本。
2.项目中使用直接引入对应的starter即可,这个场景下需要的依赖就会自动导入到项目中,简化了繁琐的依赖。
如果需要修改版本可以有两种方式:
- 重写maven属性
- 使用Maven依赖管理的就近原则
3.引入starter不仅仅是帮助我们管理了依赖,还帮助我们配置了很多配置信息,简化了大量的配置,使用更简单。
4.所有的场景启动器的底层都依赖:spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.10.RELEASE</version>
<scope>compile</scope>
</dependency>
小结:
- 引入官方starter依赖默认都可以不写版本
- 如果配置满足您当前开发需要,则默认配置即可
2.SpringBoot自动化配置初体验
目的:以web MVC自动化配置原理为例讲解,能够理解webMVC自动化配置加入了哪些依赖,做了哪些默认配置。
回忆一下:SpringMVC学习时候,我们在 SSM整合时;
添加spring及spring web mvc相关依赖
springmvc配置类:
1、扫描controller层
2、静态资源控制
3、…
servlet容器配置类:
1、扫描springmvc配置类
2、扫描spring配置类
3、设置哪些请求交给springmvc处理
4、POST请求乱码过滤器
部署还需要单独的tomcat
也就是说:我们现在需要在开发业务代码前,就必须要准备好这些环境,否则无法完成业务代码。
引入 web 开发场景启动器依赖:
<!--web开发的起步依赖 场景启动器依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
帮助我们做了以下自动化配置:
1.依赖版本和依赖的jar包都不需要开发者关注
2.自动化配置
- 自动配好SpringMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(三大组件,文件上传等)
- 自动配好Web常见功能:如:字符编码问题,静态资源管理
3.自动配好tomcat
3.SpringBoot高级-底层原理-@Configuration配置注解
目的:掌握@Configuration注解的作用及新特性
1.@Configuration:替代原始spring配置文件功能
1)编写配置类
package com.itheima.sh.config;
import com.itheima.sh.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 1、@Configuration 替代 spring配置文件(配置bean)
* 2、组件源码中包含 @Component 注解,当前类也会注册到 IOC 容器,默认类名小写
* 3、默认都是单例的
*/
@Configuration
public class MyConfig {
@Bean // 默认方法名称作为容器中的name
public User getUser() {
return new User();
}
}
2)在引导类编写代码测试:
@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
public class DataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);
// 根据name获取容器中的bean
User user1 = applicationContext.getBean("getUser", User.class);
User user2 = applicationContext.getBean("getUser", User.class);
System.out.println(user1 == user2);
MyConfig myConfig1 = applicationContext.getBean("myConfig", MyConfig.class);
MyConfig myConfig2 = applicationContext.getBean("myConfig", MyConfig.class);
System.out.println(myConfig1 == myConfig2);
// 注意:如果 MYConfig配置类没有按照规范编写,则容器中bean 的name为 类名
}
}
SpringBoot 提供一个注解和当前注解功能一样:@SpringBootConfiguration
2、proxyBeanMethods:代理bean的方法属性(since spring 5.2以后)
功能:
- proxyBeanMethods = true:Full模式,保证每个@Bean方法被调用多少次返回的组件都是单实例的
- proxyBeanMethods = false:Lite模式,每个@Bean方法被调用多少次返回的组件都是新创建的
演示:
1.默认proxyBeanMethods = true,SpringBoot会检查这个组件是否在容器中有,有则直接引用
// 默认 proxyBeanMethods=true springBoot会检查这个组件是否在容器中有,有则直接引用
User user3 = myConfig1.getUser();
System.out.println(user1 == user3); // true
2.修改 proxyBeanMethods = false,则每调一次Spring就会创建一个新的Bean对象
再次执行结果为:false,证明两次获取的bean不是同一个bean
小结:
- 组件依赖必须使用Full模式默认
- Full模式每次都会检查bean,效率较Lite模式慢
4.SpringBoot高级-底层原理-@Import注解使用
目的:能够理解@Import注解作用及4种使用方式
作用:使用@Import导入的类会被Spring加载到IOC容器中
@Import提供4种用法:
- 导入Bean
- 导入配置类
- 导入ImportSelector实现类。一般用于加载配置文件中的类
- 导入ImportBeanDefinitionRegistar实现类
实现:
1、导入Bean
package com.itheima.sh;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import java.util.Map;
@SpringBootApplication
@Import(User.class)
//会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
public class DataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);
Map<String, User> map = applicationContext.getBeansOfType(User.class);
System.out.println(map);
User user1 = applicationContext.getBean("com.itheima.sh.pojo.User", User.class);
System.out.println(user1);
}
}
2、导入配置类
package com.itheima.sh;
import com.itheima.sh.config.MyConfig;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import java.util.Map;
@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
public class DataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);
//{getUser=com.itheima.sh.pojo.User@1b4a3a1}
Map<String, User> map = applicationContext.getBeansOfType(User.class);
System.out.println(map);
User user1 = applicationContext.getBean("getUser", User.class);
System.out.println(user1);
Map<String, MyConfig> config = applicationContext.getBeansOfType(MyConfig.class);
//{com.itheima.sh.config.MyConfig=com.itheima.sh.config.MyConfig@7e848aea}
System.out.println(config);
}
}
5.SpringBoot高级-底层原理-@Import注解使用
目的:讲解@Import注解使用另外两种使用方式
步骤:
1.导入ImportSelector实现类。一般用于加载配置文件的类
2.导入ImportBeanDefinitionRegistrar实现类
实现:
导入ImportSelector实现类。一般用于加载配置文件中的类
1.编写ImportSelector实现类,MyImportSelector
2.引导类导入
package com.itheima.sh;
import com.itheima.sh.config.MyImportSelector;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import java.util.Map;
@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
//@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
@Import(MyImportSelector.class)
//3、创建MyConfig bean 名称为:类名全路径,创建带有@Bean注解方法实例,名称为:方法名称
public class DataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);
Map<String, MyConfig> map = applicationContext.getBeansOfType(MyConfig.class);
//{com.itheima.sh.config.MyConfig=com.itheima.sh.config.MyConfig@44384b4a}
System.out.println(map);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
//{getUser=com.itheima.sh.pojo.User@5cc3e49b}
System.out.println(userMap);
}
}
导入ImportBeanDefinitionRegistrar实现类
1、编写 ImportBeanDefinitionRegistrar 实现类,MyImportBeanDefinitionRegistrar
package com.itheima.sh.config;
import com.itheima.sh.pojo.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata 导入类的元注解信息
* @param registry Bean注册表
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user", beanDefinition);
}
}
2、引导类测试
package com.itheima.sh;
import com.itheima.sh.config.MyImportBeanDefinitionRegistrar;
import com.itheima.sh.pojo.User;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import java.util.Map;
@SpringBootApplication
@MapperScan(basePackages = "com.itheima.sh.mapper")
//@Import(User.class)
//1、会自动执行当前类的构造方法创建对象,存到IOC容器, bean名称为:类的全路径
//@Import(MyConfig.class)
//2、创建MyConfig bean,并且类中有 带有@Bean注解方法,创建对象存到IOC容器,bean名称为:默认方法名称
//@Import(MyImportSelector.class)
//3、创建MyConfig bean 名称为:类名全路径,创建带有@Bean注解方法实例,名称为:方法名称
@Import(MyImportBeanDefinitionRegistrar.class)
//4、创建Bean,名称:在registerBeanDefinition中定义
public class DataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DataApplication.class, args);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
//{user=com.itheima.sh.pojo.User@23c7cb18}
System.out.println(userMap);
}
}
小结:
- 讲解当前小节的目的主要是为源码准备
- 还有我们也可以知道创建Bean对象,还可以使用
@Import
四种方式
6.SpringBoot高级-底层原理@Conditional衍生条件装配
目的:理解@Conditional衍生条件装配的作用
作用:条件装配,满足Conditional指定的条件,则进行组件注入,初始化Bean对象到IOC容器。
演示:
在RedisConfig类中添加注释:
方法中定义:
类上定义:
注意:也可以添加到 类上, 满足条件则类及类中的对象生效。
小结:
- @ConditionalOnXXX注解存在的意义是:满足条件当前类或者Bean才有效,按需导入
7.SpringBoot高级@ConfigurationProperties配置绑定
目的:获取配置属性或者是配置文件指定前缀的属性信息,并初始化Bean对象到IOC容器。
将来的配置我们可以放在配置文件中,通过这个注解来读取并封装成对象。
8.SpringBoot高级-自动化配置原理-@SpringBootApplication入口分析
目的:能够理解SpringBoot自动化配置流程中@SpringBootApplication是组合注解,及每一个注解的作用。
1.SpringBoot是一个组合注解
2.@SpringBootConfiguration注解的作用
- @SpingBootConfiguration是对@Configuration注解的包装,proxyBeanMethods,默认配置true,full模式(单例Bean)
- 标识是一个配置类,所以引导类也是配置类
3.@ComponentScan注解作用
- 组件扫描,默认扫描的规则,引导类所在的包及其子包所有带注解的类
9.SpringBoot高级-自动化配置原理-@EnableAutoConfiguration自动配置注解
目的:理解@EnableAutoConfiguration自动化配置核心实现注解
1.@EnableAutoConfiguration是一个组合注解
2.@AutoConfigurationPackage注解作用
作用:利用Registrar给容器导入一系列组件
点击 Registrar
进入到源码的 register
方法,添加 断点,测试
通过debug程序发现,默认情况下将引导类的所有包及其子包的组件导入进来
3.@Import(AutoConfigurationImportSelector.class)注解作用
作用:利用selectImports方法中的getAutoConfigurationEntry方法给容器中批量导入相关组件
调用流程分析:
- 调用AutoConfigurationImportSelector类中的selectImports方法
- 调用
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类 - 利用工厂加载
Map<String, List<String>>loadSpringFactories(@Nullable ClassLoader classLoader)
得到所有的组件 - 从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
通过这个配置文件加载的自动配置:当前版本(2.3.10)是有127个默认的自动化配置
10.SpringBoot高级-自动化配置原理-按条件开启自动配置类和配置项
目的:
- 能够理解所有的自动化配置,虽然会全部加载,底层有大量的@ConditionalOnxxx,有很多自动配置类并不能完全开启
- 如果配置生效了,则会加载默认的属性配置类,实现默认的对应场景的自动化配置
讲解:
- 以上通过
META-INF/spring.factories
配置文件找到所有的自动化配置类,但 是不是全部的生效的呢?很显然是不可能全部都生效的。 - 以
JdbcTemplateAutoConfiguration
为例讲解, 进入到JdbcTemplateAutoConfiguration
自动化配置类。
//配置类,Lite模式
@Configuration(proxyBeanMethods = false)
//存在 DataSource、JdbcTemplate 类时再加载当前类
@ConditionalOnClass({DataSource.class, JdbcTemplate.class })
//容器中只有一个指定的Bean,或者这个Bean是首选Bean 加载当前类
@ConditionalOnSingleCandidate(DataSource.class)
//在配置类 DataSourceAutoConfiguration 之后执行
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
//如果条件满足:开始加载自动化配置的属性值 JdbcProperties
@EnableConfigurationProperties(JdbcProperties.class)
@Import({JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {
}
3.JdbcProperties,用于加载默认的配置,如果配置文件配置了该属性,则配置文件就生效。
4.通过@Import导入JdbcTemplateConfiguration
//配置类,Lite模式
@Configuration(proxyBeanMethods = false)
//没有JdbcOperations类型的bean时加载当前类,而 JdbcTemplate 是 JdbcOperations 接口实现类
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
JdbcProperties.Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}
验证:我们可以在我们自己的项目里面创建一个 JdbcTemplate Bean,看容器创建的Bean执行的是哪一个方法。
@Configuration
public class MyConfig {
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
System.out.println("自定义 JdbcTemplate");
return jdbcTemplate;
}
}
结果:保证容器中只有一个 Bean 实例
11.SpringBoot2高级-自动化配置原理-debug全流程
目的:能够理解SpringBoot启动的完成自动化配置及属性加载的全过程
12.SpringBoot高级-自动化配置原理-总结
- 程序启动找到自动化配置包下
META-INF/spring.factories
的EnableAutoConfiguration
- SpringBoot先加载所有的自动配置类xxxAutoConfiguration
- 每个自动配置类安装条件进行生效
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就实现了
- 定制化配置
- 用户直接自己@Bean替换底层组件
- 用户去看这个组件是获取的配置文件什么值就去修改
开发人员使用步骤总结:
- 引入场景依赖
- 查看自动配置了哪些
- 自己分析,引入场景对应的自动配置一般都生效了
- 配置文件中debug=true开启自动配置报告。Negative(不生效)/Positive(生效)
- 自己分析是否需要修改
- 参照文档修改配置项,xxxxProperties绑定了配置文件的哪些
- 自定义加入或者替换组件,@Bean、@Comonent
二、SpringBoot健康监控
1.SpringBoot高级-监控-健康监控服务
目的:能够理解健康监控actuator
的作用
讲解:
每一个微服务在云上部署以后,我们都需要对其进行监控、追踪、审计、控制等。
SpringBoot就抽取了Actuator场景,使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能。
实现:
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、启动项目,访问 http://localhost:80/actuator
3、暴露所有监控信息为HTTP
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' #以web方式暴露
endpoint:
health:
enabled: true # 开启健康检查详细信息
show-details: always
访问 http://localhost:80/actuator
会发现内容多了,里面的地址分别都可以访问,记录的是对应的健康监测的信息。
2.SpringBoot高级-监控-Admin可视化
目的:能够搭建可视化监控平台
讲解:
SpringBootAdmin有两个角色,客户端(Client)和服务端(Server)
SpringBootAdmin为注册的应用程序提供以下功能:
- 显示健康状况
- 显示详细信息
- JVM和内存指标
- micrometer.io指标
- 数据源指标
- 缓存指标
- 显示内部信息
- 关注并下载日志文件
- 查看JVM系统和环境熟悉
- 查看Spring Boot配置属性
- 支持Spring Cloud的可发布/env-和//refresh-endpoint
- 轻松的日志级别管理
- 与JMX-beans交互
- 查看线程转储
- 查看http-traces
- 查看审核事件
- 查看http端点
- 查看预定的任务
- 查看和删除活动会话(使用spring-session)
- 查看Flyway/Liquibase数据库迁移
- 下载heapdump
- 状态更改通知(通过电子邮件,Slack,Hipchat等)
- 状态更改的事件日志(非持久性)
快速入门:https://codecentric.github.io/spring-boot-admin/2.3.1/#getting-started
实现:以下为创建服务端和客户端化工程步骤:
- 搭建Server端:
1、创建 admin_server 模块,引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2、开启注解支持
package com.itheima.sh;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAdminServer
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
注意端口修改为:9999
- 搭建Client端
1、在任意服务里面引入依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
2、配置文件
# 执行admin.server地址
spring:
boot:
admin:
client:
url: http://localhost:9999 # admin 服务地址
instance:
prefer-ip: true # 显示IP
application:
name: boot_data # 项目名称
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' #以web方式暴露
endpoint:
health:
enabled: true # 开启健康检查详细信息
show-details: always
3、启动服务,访问admin Server http://localhost:9999/
三、Lombok
1、pom依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2、实体类
@Data // set/get/tostring ....
@AllArgsConstructor // 全参
@NoArgsConstructor // 无参构造
@ToString // tostring
@Accessors(chain = true) // 链式调用
@Builder // 构建者模式创建对象
@Slf4j // 日志注解支持
public class User {
private Long id;
private String userName;
private Integer sex;
private LocalDate birthday;
private Date created;
private Date modified;
}
3、测试
// User user = new User();
//user = user.setId(1L).setSex(1);
User user1 = User
.builder()
.id(1L)
.sex(1)
.created(new Date())
.build();
System.out.println("user1: "+user1);