122.【SpringBoot 源码刨析A】

122 阅读27分钟

SpringBoot2 核心技术

(一)、SpringBoot核心技术入门

官方文档: www.yuque.com/atguigu/spr…

1.Spring能做什么?

1.1、Spring 的能力

在这里插入图片描述

1.2、Spring的生态

spring.io/projects/sp…

覆盖了:
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 官方文档: docs.spring.io/spring-boot…
在这里插入图片描述
在这里插入图片描述

(二)、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("哈吉米");
    }
}

在这里插入图片描述

  1. 什么时候用到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);
    }
}

在这里插入图片描述

  1. 当容器中没有指定的组件的时候才执行
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(主启动类) 所在包下。
  1. 我们点开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}) (官方注入)
  1. 点进@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、最佳实践

  • 引入场景依赖
  • 查看自动配置了哪些(选做)
    • 自己分析,引入场景对应的自动配置一般都生效了
    • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
  • 是否需要修改
    • 参照文档修改配置项
      • 自己分析。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