SpringBoot2 核心技术
- (一)、SpringBoot核心技术入门
- 1.Spring能做什么?
- 1.1、Spring 的能力
- 1.2、Spring的生态
- 1.3、Spring5重大升级
- 1.3.1、响应式编程
- 1.3.2、内部源码设计
- 2.为什么用SpringBoot
- 2.1、SpringBoot优点
- 2.2、SpringBoot缺点
- 3.时代背景
- 3.1、微服务
- 3.2、分布式的困难
- 3.3、云原生
- 4.如何学习SpringBoot
- 4.1、查看官方文档
- (二)、SpringBoot2入门
- 1.系统要求
- 1.1、maven设置
- 2.HelloWord
- 2.1、创建maven工程
- 2.3、创建主程序
- 2.4、编写业务
- 2.5、RestController源码 ⭐
- 2.6、测试是否成功
- 2.7、简化配置 ⭐⭐
- 2.8、简化打包 ⭐⭐⭐
- (三)、了解SpringBoot自动配置原理
- 1.SpringBoot特点
- 1.1、依赖管理
- (1).父项目控制版本依赖 (自动版本仲裁机制)
- (2).自定义依赖版本
- (3).starter场景启动器
- (4).版本仲裁
- 1.2、自动配置
- (1).自动配备 Tomcat
- (2).自动配备 SpringMVC
- (3). 自动配备 常用组件
- (4).默认的包结构 (修改默认扫描路径) ⭐
- (5).自动配置 配置有用默认值
- (6).按需加载自动配置项
- 2.IOC容器功能
- 2.1、组件添加
- (1).@Configuration
- (2).@Bean、@Component、@Controller、@Service、@Repository
- (3).@ComponentScan、@Import
- (4).@Conditional
- 2.2、原生配置文件引入 (只能放在类级别的注解上)
- (1). 尚未使用 @ImportResource
- (2). 引用 @ImportResource
- 2.3、配置绑定
- (1).@ConfigurationProperties (第一种)
- (2).@EnableConfigurationProperties (第二种)
- 3.自动配置原理入门
- 3.1、引导加载自动配置类
- (1). @SpringBootConfiguration
- (2). @ComponentScan
- (3).@EnableAutoConfiguration
- (3.1).@AutoConfigurationPackage (自定义注入组件)
- (3.2).@Import({AutoConfigurationImportSelector.class}) (官方注入)
- 3.2、按需开启自动配置项
- 3.3、 修改默认配置
- 3.4、 总结
- 3.5、最佳实践
- 4.开发技巧
- 4.1 lombok 技术
- 4.2 devtools 技术
(一)、SpringBoot核心技术入门
官方文档: https://www.yuque.com/atguigu/springboot/na3pfd
1.Spring能做什么?
1.1、Spring 的能力
1.2、Spring的生态
https://spring.io/projects/spring-boot
覆盖了:
web开发
数据访问
安全控制
分布式
消息服务
移动开发
批处理
…
1.3、Spring5重大升级
1.3.1、响应式编程
1.3.2、内部源码设计
基于Java8的一些新特性,如:接口默认实现。重新设计源码架构。
2.为什么用SpringBoot
2.1、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
SpringBoot的底层是Spring.Spring的底层是Java。
2.2、SpringBoot缺点
● 人称版本帝,迭代快
,需要时刻关注变化
● 封装太深,内部原理复杂,不容易精通
3.时代背景
3.1、微服务
● 微服务是一种架构风格
● 一个应用拆分为一组小型服务
● 每个服务运行在自己的进程内,也就是可独立部署
和升级
● 服务之间使用轻量级
HTTP交互
● 服务围绕业务功能拆分
● 可以由全自动部署
机制独立部署
● 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
3.2、分布式的困难
● 远程调用
● 服务发现
● 负载均衡
● 服务容错
● 配置管理
● 服务监控
● 链路追踪
● 日志管理
● 任务调度
● …
3.3、云原生
原生应用如何上云。 Cloud Native
上云的困难
● 服务自愈
● 弹性伸缩
● 服务隔离
● 自动化部署
● 灰度发布
● 流量治理
● …
上云的解决
4.如何学习SpringBoot
4.1、查看官方文档
SpringBoot 2.4.13 官方文档: https://docs.spring.io/spring-boot/docs/2.4.13/reference/html//
(二)、SpringBoot2入门
1.系统要求
● Java 8 & 兼容java14 .
● Maven 3.3+
● idea 2019.1.2
1.1、maven设置
1.查看自己的Maven版本:
mvn -version
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>
// 使用jdk1.8进行编译
<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>
2.HelloWord
2.1、创建maven工程
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2.3、创建主程序
/**
* 主程序类
* @SpringBootApplication:这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
2.4、编写业务
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello, Spring Boot 2!";
}
}
2.5、RestController源码 ⭐
@Controller + @ResponseBody = @RestController
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller ⭐⭐
@ResponseBody ⭐⭐
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
}
2.6、测试是否成功
2.7、简化配置 ⭐⭐
有一个统一的配置文件 : application.properties
官方配置选项: 2.4.3 application.properties配置选项
2.8、简化打包 ⭐⭐⭐
在以前我们如果需要打包一个jar包是非常繁琐的,我们需要先写入配置文件,然后打包成war包,再然后利用第三方工具进行将war包转换为jar包
。
现在我们SpringBoot给我们提供了一款便捷的打包工具插件:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
然后我们在终端输入: mvn package
即可打包成功!!!
(三)、了解SpringBoot自动配置原理
1.SpringBoot特点
1.1、依赖管理
在实际开发中: 父项目是为了做依赖管理的,也就是统一管理我们软件开发的版本号。
(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>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
他的父项目的父项目几乎指定了所有版本信息
(2).自定义依赖版本
在日常工作和开发中我们会遇到SpringBoot自动生成的很多版本和我们实际需要的版本不一致的问题,我们只需要在当前的的Maven依赖管理文件中新增如下版本指定即可覆盖原有的不合实际的版本。
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.16.4</mysql.version>
</properties>
(3).starter场景启动器
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>
(4).版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
1.2、自动配置
(1).自动配备 Tomcat
引入Tomcat、配置Tomcat。
我们引入的web启动器中,底层帮我们引入了tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
点击查看web启动器的源码,发现以下Tomcat配置文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
(2).自动配备 SpringMVC
web启动器的源码依然帮助我们自动配备了webMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
<scope>compile</scope>
</dependency>
(3). 自动配备 常用组件
启动类返回的是IOC容器,我们查看这个IOC容器中的组件名都有哪些,就自动帮助我们配备了哪些组件。
package com.jsxs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
}
}
(4).默认的包结构 (修改默认扫描路径) ⭐
- 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
-
无需以前的包扫描配置
-
想要改变扫描路径,
@SpringBootApplication(scanBasePackages="com.atguigu")
或者@ComponentScan
指定扫描路径
1.在主程序的启动类上进行手动添加要扫描的位置,我们点开SpringBootApplication的注解源码发现里面存在一个value为scanBasePackages
我们只需要在这里指定扫描包的位置路径即可。
@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan = @SpringBootApplication
package com.jsxs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication(scanBasePackages="com.jsxs")
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
}
}
(5).自动配置 配置有用默认值
application.properties: 默认的配置其实都是映射到一个类上的
比如配置端口号映射的类名是 : ServerProperties.java
(6).按需加载自动配置项
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在
spring-boot-autoconfigure
包里面
如果我们查看源码的时候爆红,不是因为我们哪里写错了,而是我们的SpringBoot是按需配置的,没有使用上(使用依赖)就会爆红。
2.IOC容器功能
2.1、组件添加
(1).@Configuration
- 基本使用
- Full模式与Lite模式
-
- 示例
-
- 最佳实战
-
-
- 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
-
-
-
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
-
1.我们使用SpringMVC的时候如何进行组件添加的
在resources目录下创建 beans.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">
<!-- 1.指定我们的人类实体类并赋值id -->
<bean id="user01" class="com.jsxs.bean.User">
<!-- 2.给我们实体类进行默认赋值的操作 -->
<property name="name" value="李明"></property>
<property name="age" value="12"></property>
</bean>
<!-- 3.指定宠物实体类并赋值id -->
<bean id="cat" class="com.jsxs.bean.Pet">
<property name="name" value="哈吉米"></property>
</bean>
</beans>
2.现在我们省去了配置文件,直接使用@Configuration注解即可
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Configuration(proxyBeanMethods=false) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
@Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
- 什么时候用到Full模式或List模式呢?
组件依赖必须使用Full模式默认。其他默认是否Lite模式。通俗的讲就是如果这个容器下面没人用了我们就设置成false,如果仍然有人是用的话,我们就设置成true。
- 区别: 设置成fasle会跳过检查是否容器中已经存在,提升性能。
列子: 用户拥有容器中注册的哈吉米猫,我们要使用FULL模式,因为要保证用户有的是唯一的,即用户拥有的哈吉米猫和容器中组件的哈吉米猫是一样的。
User.java
package com.jsxs.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author Jsxs
* @Date 2023/7/1 12:11
* @PackageName:com.jsxs.bean
* @ClassName: User
* @Description: TODO
* @Version 1.0
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private String name;
private int age;
//
private Pet pet;
}
config.java 设置为FULL模式
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Configuration(proxyBeanMethods=true) ⭐// 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
@Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
(2).@Bean、@Component、@Controller、@Service、@Repository
1.SpringMVC提供的这些注解,只要在SpringBoot扫描包的范围内仍然可以进行注册组件。
1. @Bean 注册配置类组件
2. @Component 除了配置类组件不能使用,其余万能
3. @Controller 控制层组件
4. @Service 业务层组件
5. @Repository 实体类层组件
(3).@ComponentScan、@Import
1.@ComponentScan 组件
通过这个注解我们可以手动的更改SpringBoot默认的扫描路径。
2. @Import
用法:
1. @imoort 用于放在容器中组件类上。
用途
2. @imoort 用于给容器中导入 自定义组件或第三方组件
结论
3. @import引入组件和手动添加组件结果都添加到容器中去了,但是获取到的组件名有点区别: 引入的获得的名字是全限定名,手动的不是全限定名。
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Import({User.class}) ⭐⭐
@Configuration(proxyBeanMethods=true) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
@Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
package com.jsxs;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import com.jsxs.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
// 3.从IOC容器中获取组件,结果为true证明是单实列的。Bean是一个组件
Pet tom1 = run.getBean("tom", Pet.class);
Pet tom2 = run.getBean("tom", Pet.class);
System.out.println("组件"+(tom1==tom2)); // == 比较的是地址
// 4.配置类(类名)也是一个组件
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean); // 如果能打印出来,就署名我们通过类名获取一个组件成功
// 5.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
User user1 = bean.user01();
User user2 = bean.user01();
System.out.println(user1==user2); //如果被代理就为true,不被代理就为false
// 6.验证Full模式
User user01 = (User) run.getBean("user01",User.class); //从容器中获取user
Pet pet = user01.getPet();
Pet tom = run.getBean("tom", Pet.class); //假如不是代理的,那么在这里就会重新生成一个bean,如果是代理的就不会重新生成
System.out.println("验证Full:"+(pet==tom));
// 7.验证import引入组件
String[] type = run.getBeanNamesForType(User.class);//根据类型进行获取组件
System.out.println("======="); ⭐⭐⭐
for (String s : type) {
System.out.println(s);
}
}
}
(4).@Conditional
条件装配:满足Conditional
指定的条件,则进行组件注入
1.当组件中存在某个组件的时候才执行注册
1.作用域: 类上或者方法上。
假如标注到方法上,当这个条件注解为真的时候,这个方法上的注册才生效。当标注到类上的时候,当条件为假的时候,这个类上的所有方法都不生效(也就不会注入到IOC)。
@ConditionalOnBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册
我们这里对tom容器进行了注释,也就是说IOC容器中不存在tom容器了。
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Import({User.class})
@Configuration(proxyBeanMethods=true) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
public class MyConfig {
@ConditionalOnBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
// @Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
package com.jsxs;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import com.jsxs.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
// 1.测试容器中是否有tom这个组件
boolean flag = run.containsBean("tom");
System.out.println("IOC容器是否有tom容器:"+flag);
boolean b = run.containsBean("user01");
System.out.println("IOC容器中是否有user01这个容器:"+b);
}
}
- 当容器中没有指定的组件的时候才执行
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Import({User.class})
@Configuration(proxyBeanMethods=true) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
@ConditionalOnMissingBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
// @Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
package com.jsxs;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import com.jsxs.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
// 1.测试容器中是否有tom这个组件
boolean flag = run.containsBean("tom");
System.out.println("IOC容器是否有tom容器:"+flag);
boolean b = run.containsBean("user01");
System.out.println("IOC容器中是否有user01这个容器:"+b);
}
}
2.2、原生配置文件引入 (只能放在类级别的注解上)
1.作用:
我们使用SpringBoot框架之后,SpringMvc支持的beans.xml配置文件不会被SpringBoot进行解析,这时候我们想要SpringBoot帮助我们解析beans.xml
2.用法:
文件的话,我们可以在任意一个IOC容器组件类上进行@ImportResource()即可
这个注解放在任意一个IOC容器类组件上即可。(放一个即可)
classpath: 指的是resource目录下
@ImportResource("classpath:beans.xml")
(1). 尚未使用 @ImportResource
/resource/benas.xml: 我们对id名进行修改(避嫌),进行查找是否存在这两个组件
<?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">
<!-- 1.指定我们的人类实体类并赋值id -->
<bean id="haha" class="com.jsxs.bean.User">
<!-- 2.给我们实体类进行默认赋值的操作 -->
<property name="name" value="李明"></property>
<property name="age" value="12"></property>
</bean>
<!-- 3.指定宠物实体类并赋值id -->
<bean id="hehe" class="com.jsxs.bean.Pet">
<property name="name" value="哈吉米"></property>
</bean>
</beans>
查询结果:是查询不到的。因为SpringBoot识别不了这个beans.xml文件
(2). 引用 @ImportResource
package com.jsxs.config;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.*;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Import({User.class})
@Configuration(proxyBeanMethods=true) // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
//@ConditionalOnMissingBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册
@ImportResource("classpath:beans.xml")
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
@Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
package com.jsxs;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import com.jsxs.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @Author Jsxs
* @Date 2023/7/1 9:53
* @PackageName:com.jsxs
* @ClassName: MainSpringApplication
* @Description: TODO
* @Version 1.0
*/
@SpringBootApplication
public class MainSpringApplication {
public static void main(String[] args) {
// 1.返回的是我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainSpringApplication.class, args);
// 2.我们查看IOC容器里面都有哪些组件
String[] benas = run.getBeanDefinitionNames();
for (String bena : benas) {
System.out.println(bena);
}
// 9.@ImportResource ⭐
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha "+haha+" " + "hehe " +hehe);
}
}
2.3、配置绑定
就是实体类通过配置文件进行赋值
。
切记:任何一个注解都只对IOC容器生效,如果注解没有加入IOC容器中去,那么会爆红且报错
(1).@ConfigurationProperties (第一种)
前缀指的是 .属性 前面的那个单词就是前缀。
我们在使用@ConfigurationProperties注解的时候,指定的前缀就是 .属性前面的那个单词。
1.application.properties
server.port=8080
mycar.brand=BYD
mycar.price=1200
2.进行配置绑定
package com.jsxs.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Repository;
/**
* @Author Jsxs
* @Date 2023/7/1 16:34
* @PackageName:com.jsxs.bean
* @ClassName: Car
* @Description: TODO 只会在IOC容器中的组件,才会拥有SprngBoot提供的强大功能
* @Version 1.0
*/
@Data
@Repository
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "mycar") // 添加上前缀
public class Car {
private String brand;
private Integer price;
}
3.注解的源码:
这里prefix与value互为别名
package org.springframework.boot.context.properties;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
@AliasFor("prefix")
String value() default "";
@AliasFor("value")
String prefix() default "";
boolean ignoreInvalidFields() default false;
boolean ignoreUnknownFields() default true;
}
4.controller进行测试
package com.jsxs.controller;
import com.jsxs.bean.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @Author Jsxs
* @Date 2023/7/1 9:55
* @PackageName:com.jsxs.controller
* @ClassName: IndexController
* @Description: TODO
* @Version 1.0
*/
@RestController
public class IndexController {
@Resource
Car car;
@RequestMapping("/hello")
public String hello(){
return "hello";
}
@RequestMapping("/car")
public Car car(){
return car;
}
}
(2).@EnableConfigurationProperties (第二种)
1. 前提条件
(1).实体类上可以不用加@Compont注入到IOC容器中
(2).实体类上需要指定配置绑定的前缀 @ConfigurationProperties(prefix = "mycar") // 添加上前缀
(3).@EnableConfigurationProperties(实体类.class) 需要放在任意IOC容器组件类上
2.
@EnableConfigurationProperties(实体类.class) = 配置绑定 + @Component依赖注入
3.使用场景:
当我们引用第三方默认的配置时候,第三方在实体类上没有添加@Component注入到IOC容器的时候,我们需要使用第二种方式。
实体类
package com.jsxs.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Repository;
/**
* @Author Jsxs
* @Date 2023/7/1 16:34
* @PackageName:com.jsxs.bean
* @ClassName: Car
* @Description: TODO 只会在IOC容器中的组件,才会拥有SprngBoot提供的强大功能
* @Version 1.0
*/
@Data
//@Repository 这次把IOC容器组件给去掉 ⭐
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "mycar") // 添加上前缀 ⭐⭐
public class Car {
private String brand;
private Integer price;
}
配置类上
package com.jsxs.config;
import com.jsxs.bean.Car;
import com.jsxs.bean.Pet;
import com.jsxs.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
/**
* @Author Jsxs
* @Date 2023/7/1 12:30
* @PackageName:com.config
* @ClassName: MyConfig
* @Description: TODO 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实列的,
* @Description: TODO 2.配置类(类名)本身也是一个组件,即在这个列子中有三个组件并不是俩个。
* @Description: TODO 3.@Configuration(proxyBeanMethods=true)代理bean,也就是无论外部调用多少次实列都是一样的即单列。否则不是单实列
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
* @Version 1.0
*/
@Import({User.class})
@Configuration(proxyBeanMethods=true) ⭐⭐⭐ // 告诉SpringBoot这是一个配置类,相当于以前的配置文件 beans.xml
//@ConditionalOnMissingBean(name = "tom") // 当整个IOC容器中存在tom这个容器,我们就注册user01这个组件否则不注册
@ImportResource("classpath:beans.xml")
@EnableConfigurationProperties(Car.class) ⭐⭐⭐⭐ // 1.开启配置绑定功能。 2.把Car这个属性自动注入到容器中
public class MyConfig {
@Bean // 1. 这里相当于我们配置文件中的<bena></bean>标签
// 2. User对应的是我们配置文件的class非全限定名, user01对应我们配置文件的id
public User user01() {
// FULL模式人拥有宠物
return new User("李明",12,this.cat());
}
@Bean("tom") // 相当于我们配置文件的bean标签
public Pet cat(){ // Pet指的是calss的非全限定名, cat指定的是id
return new Pet("哈吉米");
}
}
3.自动配置原理入门
3.1、引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
======================
(1). @SpringBootConfiguration
- @Configuration。代表当前是一个配置类
(2). @ComponentScan
- 指定扫描哪些,Spring注解;
(3).@EnableAutoConfiguration
1.@EnableAutoConfiguration的合成
1.注解的合成:
@EnableAutoConfiguration= @AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class)
2.
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
(3.1).@AutoConfigurationPackage (自定义注入组件)
自动配置包?指定了默认的包规则 (即我们主启动类下的包)
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用 Registrar 给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication(主启动类) 所在包下。
- 我们点开Registar.class这个源代码发现里面存在两个方法
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
⭐ AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
在星星的位置打上断点,发现我们的元数据上的路径在主启动类上。
我们通过计算的到: 导入的是我们主启动类下所在的包中的组件。
(3.2).@Import({AutoConfigurationImportSelector.class}) (官方注入)
- 点进@Import({AutoConfigurationImportSelector.class})找到
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
⭐ AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 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
这里导入的130个包就是 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
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
3.2、按需开启自动配置项
虽然我们130个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。
按需开启自动配置的原理是: 按条件注入
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默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
@Bean
@ConditionalOnMissingBean //假如没有的时候自动创建,用户创建了就不自动创建了。
public CharacterEncodingFilter characterEncodingFilter() {
}
3.4、 总结
- SpringBoot
先加载所有的自动配置类
xxxxxAutoConfiguration 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值
。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 定制化配置
-
- 用户直接自己
@Bean
替换底层的组件
- 用户直接自己
-
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration(自动装配文件)
—> 组件 —> xxxxProperties (实体类)
里面拿值 ----> application.properties (主配置文件)
3.5、最佳实践
- 引入场景依赖
-
- 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
-
-
-
- 自己分析。xxxxProperties绑定了配置文件的哪些。
-
- 自定义加入或者替换组件
-
- @Bean、@Component。。。
-
- 自定义器 XXXXXCustomizer;
-
- …
4.开发技巧
4.1 lombok 技术
1. 可以帮助我们配置实体类
2. 拥有@Slf4j 日志配置注解
===============================简化JavaBean开发===================================
@NoArgsConstructor
//@AllArgsConstructor
@Data
@ToString
@EqualsAndHashCode
public class User {
private String name;
private Integer age;
private Pet pet;
public User(String name,Integer age){
this.name = name;
this.age = age;
}
}
================================简化日志开发===================================
@Slf4j
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(@RequestParam("name") String name){
log.info("请求进来了....");
return "Hello, Spring Boot 2!"+"你好:"+name;
}
}
4.2 devtools 技术
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
项目或者页面修改以后:Ctrl+F9
;