一.Spring Initializr创建向导
1.新建一个空项目
2.在新创建的空项目里,新建Module
3. 选择Spring Initializr
4.选择Spring Boot的版本3+以上
5.创建好的一个项目结构
controller包是自己创建的
6.项目结构分析
spingboot主程序
package com.example.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication //加上这个注解,表示这是一个SpringBoot应用
public class Boot302DemoApplication {
public static void main(String[] args) {
SpringApplication.run(Boot302DemoApplication.class, args);
}
}
7.测试
com.example.boot下创建controller包-再在该包下创建一个HelloController类
@ResponseBody //获取的是文本,而不是跳转页面的
@Controller
这两个注解相当于一个@RestController
运行主类
运行结果:
在浏览器中输入localhost:8080/haha
以上一个简单的Springboot项目测试完成
二.组件注册
SpringBoot摒弃XML配置方式,改为全注解驱动
@Configuration、@SpringBootConfiguration
@Bean、@Scope
@Controller、 @Service、@Repository、@Component
@Import
@ComponentScan
1.@Configuration与 @Bean的使用
(1)组件在容器中的名字默认是方法名
举例:
新建bean包,再包下创建User和Cat两个类
新建config包,再该包下创建AppConfig类
User和Cat类下的内容
User类
package com.example.boot.bean;
public class User {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Cat类
package com.example.boot.bean;
public class Cat {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
AppConfig类
//组件在容器中的名字默认是方法名
package com.example.boot.config;
import com.example.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @description
* @author: Admin
* @create: 2023/12/7 9:35
*/
@Configuration //这是一个配置类,代替之前的配置文件
public class AppConfig {
//组件在容器中的名字是方法名
@Bean //该注解替代之前的bean标签,就是在ioc.xml里的配置的标签
public User user01(){
var user=new User();
user.setId(1L);
user.setName("小苏");
return user;
}
}
ioc.xml里的配置信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.example.boot.bean.User">
<property name="id" value="1"></property>
<property name="name" value="zhangsan"></property>
</bean>
<bean id="cat" class="com.example.boot.bean.Cat">
<property name="id" value="1"></property>
<property name="name" value="Tom"></property>
</bean>
</beans>
运行主类:
再运行结果中查询user01
(2)组件在容器中的名字默认是方法名,但是可以直接修改注解的值
举例:
运行主类,再主类的结果中查询hahaha
2.@Scope应用
组件默认都是单实例),想要变成多实例(每次获取都会重新创建对象),可添加@Scope(“prototype”)
3.@SpringBootConfiguration
与@Configuration注解差不多
4.@Import
@Import也是放在配置类中的
三.条件注解
如果注解指定的条件成立,则触发指定行为
@ConditionalOnXxx
举例常见的
@ConditionalOnClass:如果类路径中存在这个类,则触发指定行为
@ConditionalOnMissingClass:如果类路径中不存在这个类,则触发指定行为
@ConditionalOnBean:如果容器中存在这个Bean(组件),则触发指定行为
@ConditionalOnMissingBean:如果容器中不存在这个Bean(组件),则触发指定行为
四.属性绑定
@ConfigurationProperties: 声明组件的属性和配置文件哪些前缀开始项进行绑定
@EnableConfigurationProperties:快速注册注解:
- 场景:SpringBoot默认只扫描自己主程序所在的包。如果导入第三方包,即使组件上标注了 @Component、@ConfigurationProperties 注解,也没用。因为组件都扫描不进来,此时使用这个注解就可以快速进行属性绑定并把组件注册进容器
将容器中任意组件(Bean)的属性值和配置文件的配置项的值进行绑定
- 1、给容器中注册组件(@Component、@Bean)
- 2、使用@ConfigurationProperties 声明组件和配置文件的哪些配置项进行绑定
举例:
在配置文件(application.properties)中加入如下:
新建一个Pig类
Pig类
- 1、给容器中注册组件(@Component或者@Bean)
- 2、使用@ConfigurationProperties 声明组件和配置文件的哪些配置项进行绑定
package com.example.boot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @description
* @author: Admin
* @create: 2023/12/7 14:16
*/
@ConfigurationProperties(prefix = "pig") //prefix后面的名字是application.properties里配置里自己写的
@Component
public class Pig {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "Pig{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行主类结果:
(乱码解决方法:File->Settings->File encofings中的编码格式都改为utf-8)
五.自动配置机制
1. 初步理解
- 自动配置的 Tomcat、SpringMVC 等
- 导入场景,容器中就会自动配置好这个场景的核心组件。
- 以前:DispatcherServlet、ViewResolver、CharacterEncodingFilter....
- 现在:自动配置好的这些组件
- 验证:容器中有了什么组件,就具有什么功能
public static void main(String[] args) {
//局部变量类型的自动推断
var ioc = SpringApplication.run(MainApplication.class, args);
//1、获取容器中所有组件的名字
String[] names = ioc.getBeanDefinitionNames();
//2、挨个遍历:
// dispatcherServlet、beanNameViewResolver、characterEncodingFilter、multipartResolver
// SpringBoot把以前配置的核心组件现在都给我们自动配置好了。
for (String name : names) {
System.out.println(name);
}
}
- 默认的包扫描规则
-
@SpringBootApplication
标注的类就是主程序类 - SpringBoot只会扫描主程序所在的包及其下面的子包,自动的component-scan功能自定义扫描路径
- @SpringBootApplication(scanBasePackages = "com.atguigu")
-
@ComponentScan("com.atguigu")
直接指定扫描的路径
- 配置默认值
- 配置文件的所有配置项是和某个类的对象值进行一一绑定的。
- 绑定了配置文件中每一项值的类: 属性类。
- 比如:
-
ServerProperties
绑定了所有Tomcat服务器有关的配置 -
MultipartProperties
绑定了所有文件上传相关的配置 - ....参照官方文档:或者参照 绑定的 属性类。
- 按需加载自动配置
- 导入场景
spring-boot-starter-web
- 场景启动器除了会导入相关功能依赖,导入一个
spring-boot-starter
,是所有starter
的starter
,基础核心starter -
spring-boot-starter
导入了一个包spring-boot-autoconfigure
。包里面都是各种场景的AutoConfiguration
自动配置类 - 虽然全场景的自动配置都在
spring-boot-autoconfigure
这个包,但是不是全都开启的。
- 导入哪个场景就开启哪个自动配置
总结: 导入场景启动器、触发 spring-boot-autoconfigure
这个包的自动配置生效、容器中就会具有相关场景的功能
2.完整流程
思考:
1、SpringBoot怎么实现导一个starter
、写一些简单配置,应用就能跑起来,我们无需关心整合
2、为什么Tomcat的端口号可以配置在application.properties
中,并且Tomcat
能启动成功?
3、导入场景后哪些自动配置能生效?
自动配置流程细节梳理:
1、导入starter-web
:导入了web开发场景
- 1、场景启动器导入了相关场景的所有依赖:
starter-json
、starter-tomcat
、springmvc
- 2、每个场景启动器都引入了一个
spring-boot-starter
,核心场景启动器。 - 3、核心场景启动器引入了
spring-boot-autoconfigure
包。 - 4、
spring-boot-autoconfigure
里面囊括了所有场景的所有配置。 - 5、只要这个包下的所有类都能生效,那么相当于SpringBoot官方写好的整合功能就生效了。
- 6、SpringBoot默认却扫描不到
spring-boot-autoconfigure
下写好的所有配置类。(这些配置类给我们做了整合操作),默认只扫描主程序所在的包。
2、主程序:@SpringBootApplication
- 1、
@SpringBootApplication
由三个注解组成@SpringBootConfiguration
、@EnableAutoConfiguratio
、@ComponentScan
- 2、SpringBoot默认只能扫描自己主程序所在的包及其下面的子包,扫描不到
spring-boot-autoconfigure
包中官方写好的配置类 - 3、
@EnableAutoConfiguration
:SpringBoot 开启自动配置的核心。
- 1. 是由
@Import(AutoConfigurationImportSelector.class)
提供功能:批量给容器中导入组件。 - 2. SpringBoot启动会默认加载 142个配置类。
- 3. 这142个配置类来自于
spring-boot-autoconfigure
下META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件指定的 - 项目启动的时候利用 @Import 批量导入组件机制把
autoconfigure
包下的142xxxxAutoConfiguration
类导入进来(自动配置类) - 虽然导入了
142
个自动配置类
- 4、按需生效:
- 并不是这
142
个自动配置类都能生效 - 每一个自动配置类,都有条件注解
@ConditionalOnxxx
,只有条件成立,才能生效
3、xxxxAutoConfiguration
自动配置类
- 1、给容器中使用@Bean 放一堆组件。
- 2、每个自动配置类都可能有这个注解
@EnableConfigurationProperties(ServerProperties.class)
,用来把配置文件中配的指定前缀的属性值封装到xxxProperties
属性类中 - 3、以Tomcat为例:把服务器的所有配置都是以
server
开头的。配置都封装到了属性类中。 - 4、给容器中放的所有组件的一些核心参数,都来自于
xxxProperties
。xxxProperties
都是和配置文件绑定。 - 只需要改配置文件的值,核心组件的底层参数都能修改
4、写业务,全程无需关心各种整合(底层这些整合写好了,而且也生效了)
核心流程总结:
1、导入starter
,就会导入autoconfigure
包。
2、autoconfigure
包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,里面指定的所有启动要加载的自动配置类
3、@EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来。xxxAutoConfiguration 是有条件注解进行按需加载
4、xxxAutoConfiguration
给容器中导入一堆组件,组件都是从 xxxProperties
中提取属性值
5、xxxProperties
又是和配置文件进行了绑定
效果:导入starter
、修改配置文件,就能修改底层行为。
3. 如何学好SpringBoot
框架的框架、底层基于Spring。能调整每一个场景的底层行为。100%项目一定会用到底层自定义
摄影:
- 傻瓜:自动配置好。
- 单反:焦距、光圈、快门、感光度....
- 傻瓜+单反:
- 理解自动配置原理
- 导入starter --> 生效xxxxAutoConfiguration --> 组件 --> xxxProperties --> 配置文件
- 理解其他框架底层
- 拦截器
- 可以随时定制化任何组件
- 配置文件
- 自定义组件
普通开发:导入starter
,Controller、Service、Mapper、偶尔修改配置文件
高级开发:自定义组件、自定义配置、自定义starter
核心:
- 这个场景自动配置导入了哪些组件,我们能不能Autowired进来使用
- 能不能通过修改配置改变组件的一些默认参数
- 需不需要自己完全定义这个组件
- 场景定制化
最佳实战:
- 选场景,导入到项目
- 官方:starter
- 第三方:去仓库搜
- 写配置,改配置文件关键项
- 数据库参数(连接地址、账号密码...)
- 分析这个场景给我们导入了哪些能用的组件
- 自动装配这些组件进行后续使用
- 不满意boot提供的自动配好的默认组件
- 定制化
- 改配置
- 自定义组件
整合redis:
- 选场景:
spring-boot-starter-data-redis
- 场景AutoConfiguration 就是这个场景的自动配置类
- 写配置:
- 分析到这个场景的自动配置类开启了哪些属性绑定关系
@EnableConfigurationProperties(RedisProperties.class)
- 修改redis相关的配置
- 分析组件:
- 分析到
RedisAutoConfiguration
给容器中放了StringRedisTemplate
- 给业务代码中自动装配
StringRedisTemplate
- 定制化
- 修改配置文件
- 自定义组件,自己给容器中放一个
StringRedisTemplate