当前位置: 首页 > news >正文

Web后端进阶:springboot原理(面试多问)

1.配置优先级

3种配置文件:

  • application.properties
server.port=8081
  • application.yml
server:port: 8082
  • application.yaml
server:port: 8082

2种外部属性的配置(Java系统属性、命令行参数):

  • Java系统属性配置 (格式: -Dkey=value)
-Dserver.port=9000
  • 命令行参数 (格式:–key=value)
--server.port=10010

优先级(从低到高):

  • application.yaml(忽略)
  • application.yml
  • application.properties
  • java系统属性(-Dxxx=xxx)
  • 命令行参数(–xxx=xxx)

2.Bean的管理

2.1 Bean的作用域

在这里插入图片描述

  • 可以借助Spring中的@Scope注解来进行配置作用域

[图片]

注意事项:

  • IOC容器中的bean默认使用的作用域:singleton (单例)
  • 默认singleton的bean,在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用时)
  • prototype的bean,每一次使用该bean的时候都会创建一个新的实例
  • 实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性

2.2第三方Bean

之前我们所配置的bean,像controller、service,dao三层体系下编写的类,这些类都是我们在项目当中自己定义的类(自定义类)。当我们要声明这些bean,也非常简单,我们只需要在类上加上@Component以及它的这三个衍生注解(@Controller、@Service、@Repository),就可以来声明这个bean对象了。
但是在我们项目开发当中,还有一种情况就是这个类它不是我们自己编写的,而是我们引入的第三方依赖当中提供的,那么此时我们是无法使用 @Component 及其衍生注解来声明bean的,此时就需要使用@Bean注解来声明bean 了。

演示1:

  • 在启动类中直接声明这个Bean。比如:我们可以将我们之前使用的阿里云OSS操作的工具类,基于@Bean注解的方式来声明Bean。
import com.itheima.utils.AliyunOSSOperator;
import com.itheima.utils.AliyunOSSProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;@ServletComponentScan
@EnableScheduling
@SpringBootApplication
public class TliasWebManagementApplication {public static void main(String[] args) {SpringApplication.run(TliasWebManagementApplication.class, args);}@Beanpublic AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties ossProperties) {return new AliyunOSSOperator(ossProperties);}
}

演示2:
若要管理的第三方 bean 对象,建议对这些bean进行集中分类配置,可以通过 @Configuration 注解声明一个配置类。【推荐】

package com.itheima.config;import com.itheima.utils.AliyunOSSOperator;
import com.itheima.utils.AliyunOSSProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class OSSConfig {@Beanpublic AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties ossProperties) {return new AliyunOSSOperator(ossProperties);}
}
  • 通过@Bean注解的name 或 value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。
  • 如果第三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配。

3.SpringBoot原理

3.1起步依赖

在这里插入图片描述
当我们引入了 spring-boot-starter-web 之后,maven会通过依赖传递特性,将web开发所需的常见依赖都传递下来。
在这里插入图片描述

3.2自动配置

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。
在这里插入图片描述

3.2.1实现方案

3.2.1.1方案一

@ComponentScan组件扫描

@SpringBootApplication
@ComponentScan({"com.itheima","com.example"}) //指定要扫描的包
public class SpringbootWebConfigApplication {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfigApplication.class, args);}
}
3.2.1.2方案二

@Import导入

  • 导入形式主要有以下几种:
    1. 导入普通类
    2. 导入配置类
    3. 导入ImportSelector接口实现类

1). 使用@Import导入普通类:

@Import(TokenParser.class) //导入的类会被Spring加载到IOC容器中
@SpringBootApplication
public class SpringbootWebConfigApplication {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfigApplication.class, args);}
}

2). 使用@Import导入配置类

  • 配置类
@Configuration
public class HeaderConfig {@Beanpublic HeaderParser headerParser(){return new HeaderParser();}@Beanpublic HeaderGenerator headerGenerator(){return new HeaderGenerator();}
}
  • 启动类
@Import(HeaderConfig.class) //导入配置类
@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}
}

3). 使用@Import导入ImportSelector接口实现类:

  • ImportSelector接口实现类
public class MyImportSelector implements ImportSelector {public String[] selectImports(AnnotationMetadata importingClassMetadata) {//返回值字符串数组(数组中封装了全限定名称的类)return new String[]{"com.example.HeaderConfig"};}
}
  • 启动类
@Import(MyImportSelector.class) //导入ImportSelector接口实现类
@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}
}

4). 使用第三方依赖提供的 @EnableXxxxx注解(best)

  • 第三方依赖中提供的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)//指定要导入哪些bean对象或配置类
public @interface EnableHeaderConfig { 
}
  • 在使用时只需在启动类上加上@EnableXxxxx注解即可
@EnableHeaderConfig  //使用第三方依赖提供的Enable开头的注解
@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}
}

3.2.2原理分析

3.2.2.1源码跟踪

源码跟踪技巧:
在跟踪框架源码的时候,一定要抓住关键点,找到核心流程。一定不要从头到尾一行代码去看,一个方法的去研究,一定要找到关键流程,抓住关键点,先在宏观上对整个流程或者整个原理有一个认识,有精力再去研究其中的细节。

在这里插入图片描述
在@SpringBootApplication注解中包含了:

  • 元注解(不再解释)
  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

自动配置源码小结:
自动配置原理源码入口就是 @SpringBootApplication 注解,在这个注解中封装了3个注解,分别是:

  • @SpringBootConfiguration
    • 声明当前类是一个配置类
  • @ComponentScan
    • 进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)
  • @EnableAutoConfiguration
    • 封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类)
      在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。

当SpringBoot程序启动时,就会加载配置文件当中所定义的配置类,并将这些配置类信息(类的全限定名)封装到String类型的数组中,最终通过@Import注解将这些配置类全部加载到Spring的IOC容器中,交给IOC容器管理。

3.2.2.2 @Conditional

@Conditional注解:

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器中。
  • 位置:方法、类
  • @Conditional本身是一个父注解,派生出大量的子注解:
    • @ConditionalOnClass:判断环境中有对应字节码文件,才注册bean到IOC容器。
    • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。
    • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

最后再给大家梳理一下自动配置原理:
在这里插入图片描述

自动配置的核心就在@SpringBootApplication注解上,SpringBootApplication这个注解底层包含了3个注解,分别是:

  • @SpringBootConfiguration
  • @ComponentScan
  • @EnableAutoConfiguration

@EnableAutoConfiguration这个注解才是自动配置的核心。

  • 它封装了一个@Import注解,Import注解里面指定了一个ImportSelector接口的实现类。
  • 在这个实现类中,重写了ImportSelector接口中的selectImports()方法。
  • 而selectImports()方法中会去读取两份配置文件,并将配置文件中定义的配置类做为selectImports()方法的返回值返回,返回值代表的就是需要将哪些类交给Spring的IOC容器进行管理。
  • 那么所有自动配置类的中声明的bean都会加载到Spring的IOC容器中吗? 其实并不会,因为这些配置类中在声明bean时,通常都会添加@Conditional开头的注解,这个注解就是进行条件装配。而Spring会根据Conditional注解有选择性的进行bean的创建。
  • @Enable 开头的注解底层,它就封装了一个注解 import 注解,它里面指定了一个类,是 ImportSelector 接口的实现类。在实现类当中,我们需要去实现 ImportSelector 接口当中的一个方法 selectImports
    这个方法。这个方法的返回值代表的就是我需要将哪些类交给 spring 的 IOC容器进行管理。
  • 此时它会去读取两份配置文件,一份儿是 spring.factories,另外一份儿是 autoConfiguration.imports。而在 autoConfiguration.imports
    这份儿文件当中,它就会去配置大量的自动配置的类。
  • 而前面我们也提到过这些所有的自动配置类当中,所有的 bean都会加载到 spring 的 IOC 容器当中吗?其实并不会,因为这些配置类当中,在声明 bean 的时候,通常会加上这么一类@Conditional
    开头的注解。这个注解就是进行条件装配。所以SpringBoot非常的智能,它会根据 @Conditional
    注解来进行条件装配。只有条件成立,它才会声明这个bean,才会将这个 bean 交给 IOC 容器管理。

3.2.3自定义starter

3.2.3.1实现
  • 第1步:创建自定义starter模块 aliyun-oss-spring-boot-starter(进行依赖管理)
    • 把阿里云OSS所有的依赖统一管理起来
  • 第2步:创建autoconfigure模块 aliyun-oss-spring-boot-autoconfigure
    • 在starter中引入autoconfigure (我们使用时只需要引入starter起步依赖即可)
  • 第3步:在autoconfigure模块aliyun-oss-spring-boot-autoconfigure中完成自动配置
    1. 定义一个自动配置类,在自动配置类中将所要配置的bean都提前配置好
    2. 定义配置文件,把自动配置类的全类名定义在配置文件(META-INF/spring/xxxx.imports)中
http://www.lryc.cn/news/600677.html

相关文章:

  • React入门学习——指北指南(第五节)
  • JavaScript手录06-函数
  • 【RK3568 PWM 子系统(SG90)驱动开发详解】
  • 数据赋能(336)——技术平台——智能化运营
  • Java动态调试技术原理
  • 【RocketMQ】一分钟了解RocketMQ
  • 告别复杂配置!Spring Boot优雅集成百度OCR的终极方案
  • Windows 平台源码部署 Dify教程(不依赖 Docker)
  • 《C++ list 完全指南:从基础到高效使用》
  • Linux——线程同步
  • InvokeRepeating避免嵌套调用
  • C++编程学习(第16天)
  • 7月26日京东秋招第一场第一题
  • 【第二章-数据的表示和运算】
  • 基于java的在线教育平台管理系统、在线学习系统的设计与实现
  • 【机器学习-2】 | 决策树算法基础/信息熵
  • 背包问题及 LIS 优化
  • 【Ubuntu】发展历程
  • 排序算法,咕咕咕
  • 疏老师-python训练营-Day26函数专题1:函数定义与参数
  • Linux的生态与软件安装
  • 深入浅出学习 KNN 算法:从原理到数字识别实践
  • Matrix Theory study notes[5]
  • 7月26日京东秋招第一场第二题
  • 黑屏运维OceanBase数据库的常见案例
  • [2025CVPR:图象合成、生成方向]WF-VAE:通过小波驱动的能量流增强视频 VAE 的潜在视频扩散模型
  • 数据结构预备知识
  • 小电流驱动大电流:原理、实现方式与应用前景
  • Flutter开发实战之动画与交互设计
  • 四通OKI5560SC针式打印机如何复位清零和恢复出厂设置??