【狂神说Java】SpringBoot最新教程IDEA版通俗易懂_哔哩哔哩_bilibili
一、剖析pom.xml文件
1.spring-boot-dependencies 核心依赖
打开springboot的配置文件pom.xml(maven项目的核心配置文件),通过深入其父项目,可以查看其调用关系。
通过两层的深入后,就到底了。最底层的是spring-boot-dependencies项目,它也在我们的本地仓库里。
spring-boot-dependencies存放springboot项目的核心依赖。并且都写好了依赖的版本号,我们导入springboot项目依赖时候不需要指定版本,就因为有这些版本仓库。
but但是如果我们不想用springboot给我们指定的版本怎么办?后面再说,反正有办法。
而且在spring-boot-parent里配置好了资源过滤,不需要我们再去手动配置了
2. 启动器
<dependencies>
<!-- web的启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- test的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
springboot会把某个场景下用到的所有依赖打包成一个启动器,只要我们在pom.xml里加载了这个启动器,就导入了这个场景需要的所有依赖。比如我们想要用springboot实现web项目,就就要web场景,就导入spring-boot-starter-web启动器,他就会帮我们导入web场景所需要的所有依赖。我们要使用什么功能,只需要找到对应的启动器starter就行了。官网中给出了所有的starter.
二、@SpringBootApplication自动装配原理
“自动装配”里面的“自动”一词好理解,那“装配”是指装配什么呢?
装配的是bean。这种自动装配实际上是spring框架<bean>依赖注入的升级版本,通过注解进行自动装配。
我们通过主程序来看一下,是怎样对一个项目进行自动装配的。
//@SpringBootApplication 标注这个类是一个springboot的应用
@SpringBootApplication
public class Springboot01Application {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(Springboot01Application.class, args);
}
}
然后,我们深入@SpringBootApplication这个注解,可以看到这个注解主要由下面3个核心注解组成。
然后我们继续深入
@SpringBootConfiguration :仅仅用来说明主启动类也被注入到spring容器中了
@Configuration :
@Component: 说明本质上是一个spring的组件,说明SpringBootApplication这个启动类和@Service,@Controller一样已经被实例化并且注入到IOC容器中了,所以主程序才可以直接通过SpringApplication.run(.class)以反射的方式启动
@EnableAutoConfiguration :自动装配
@AutoConfigurationPackage :自动配置包
@Import(AutoConfigurationPackages.Registrar.class) :自动配置‘包注册’
@Import(AutoConfigurationImportSelector.class):自动配置‘导入选择’
@ComponentScan
第一个注解@SpringBootConfiguration仅仅用来说明主启动类SpringBootApplication(当然主启动类可以改名字哈)和@Service啥的一样也被注入到spring容器中了,完全没有涉及到springboot的核心——自动装配哈。第二个注解@EnableAutoConfiguration是负责自动装配场景的。第三个注解是负责自动装配自定义的java类的。
这个图看不懂的话直接看下面这段话吧:
@EnableAutoConfiguration的底层会去org.springframework.boot:spring-boot-autoconfigure包下的/META-INF/spring.factories(但是后来搬家到了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
)文件里读取所有的自动配置,把下图中右边的配置信息全都读到一个Properties properties对象里,但是读进来了以后并不生效(用到哪个再让哪个生效,全部生效岂不是太浪费资源了吗),只有导入对应的启动器starter,自动装配就会生效,配置成功!
从上图中可以看到spring.factories里已经不存放配置信息了,而是换到了下图中,但是我们下面方便叙述,还是称其为spring.factories文件:
那么底层是如何实现“导入的配置先不生效,导入启动器以后才生效”的呢?随便从spring.factories里点进去一个我们没有加载过的配置。发现有个@ConditionalOn注解,里面的“条件”爆红了,说明条件不满足,那就不配置这个东西。
=======如果面试官让你讲一下springboot的自动装配原理的话,讲到这里就OK了,但是下面的也了解一下啦========
导入了依赖以后,springboot会实现自动装配。此时配置的信息都是默认值,如果我们想要修改,就要写yml配置文件去进行注入的。
写在里面的东西会被xxxxProperties类给自动加载,然后、、、看图吧
但是只要写上yml就能配置成功了吗?
比如我想配置activemq,我在application.yml里写了的配置activemq
spring:
activemq:
broker-url:
就配好了吗?怎么可能呀,我们根本没导入activemq的依赖好吗,缺少activemq-starter场景,光有配置有什么用,就像配置好了mysql的端口号和用户名,但是没集成mysql有什么用。法(一)我们来到activemq的配置类中去看,也能发现无法实现activemq的配置,因为缺少条件。
法(二) 或者用这一行配置去查看什么配置生效了,什么配置没生效
debug: true
三、主启动类如何运行
四、配置文件yml
1. 命名要求和语法结构
创建spring initializer项目后,自动创建一个application.properties配置文件,但是官方推荐使用yml。所以删掉application.properties,自己建一个application.yml/application.yaml。
注意:命名必须是application,这也是约定大于配置的一种约定!但是如果你非要自己起个名字,也是可以的,怎么配上网查吧
2. 语法
在yml中的配置会注入到配置类中
# 对空格的要求十分高!
# 1. key value
port: 8051
# 2. 配置对象
student:
name: qinjiang
age: 23
# 配置对象的简单方法
student2: {name: qinjiang,age: 23}
# 3. 配置数组
pets:
- cat
- dog
- pig
# 配置数组的简单方法
pets2: [cat,dog,pig]
3. springboot如何读取yml配置文件(实现自动配置后的注入)
我们导入依赖以后,springboot就帮我们进行自动配置。此时都是采用默认的配置,如果我们想要改动怎么办?或者我们加入的新东西在springboot自动配置的范围之外,如何自己手动配置呢?(底层肯定是调用setter方法去改呀!)
之前,我们会写一个配置类,然后用 @Value注释给各个成员变量(配置)手动赋值,yml就是取代配置类中的@Value,直接把配置的值写在yml里,然后用一个@ConfigurationProperits(prefix=" ")实现注入,这就是yml在实际开发中的应用。
配置类.java
@Component //实现spring注入
@ConfigurationProperties(prefix = "clientconfig") //必须是小写,这里指定了yml里它的名字
public class ClientConfig {
private String name;
private Integer serverPort;
private Map test;
public ClientConfig(){
}
public ClientConfig(String name,Integer serverPort,Map test){
this.name = name;
this.serverPort = serverPort;
this.test = test;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getServerPort() {
return serverPort;
}
public void setServerPort(Integer serverPort) {
this.serverPort = serverPort;
}
public Map getTest() {
return test;
}
public void setTest(Map test) {
this.test = test;
}
@Override
public String toString() {
return "ClientConfig{" +
"name='" + name + '\'' +
", serverPort='" + serverPort + '\'' +
", test=" + test +
'}';
}
}
application.yml
# spring注入,对象名必须小写
clientconfig:
name: myclient
serverPort: 9200 # 变量名可以大写
test: {k1: v1,k2: v2}
测试类
@SpringBootTest
class Springboot01ApplicationTests {
@Autowired
ClientConfig clientConfig;
@Test
void contextLoads() {
System.out.println(clientConfig.toString());
}
}
如果用@Value的话:
@Component
public class ClientConfig {
@Value("value绑定")
private String name;
@Value("4334")
4.JSR303校验约束注入数据
@Validated注解再配合一个控制注解使用,当注入的数据不符合约束就会报错
有以下约束:
举例:
5. 如果你非要用application.properties去写,记得改UTF-8编码
application默认用ASCII编码,如果不改,配置的中文将是乱码。
五、配置文件可以放置的4个位置
file指的就是项目
六、多个环境的配置
实际开发中,我们的测试环境和开发环境的配置是不同的,需要写不同的配置,但是yml的强大之处在于不同的配置可以写在同一个yml文件里,用---分割
# 对空格的要求十分高!
server:
port: 8081
spring:
profiles:
active: test # 使用测试环境
---
server:
port: 8082
spring:
config:
activate:
on-profile: dev # 开发环境
---
server:
port: 8083
spring:
config:
activate:
on-profile: test # 测试环境