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

day14-SpringBoot 原理篇

一、配置优先级

SpringBoot 中支持三种格式的配置文件:
在这里插入图片描述

注意事项

  • 虽然 springboot 支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置 (yml 是主流)。

配置文件优先级排名(从高到低):

  1. properties 配置文件
  2. yml 配置文件
  3. yaml 配置文件

SpringBoot 除了支持配置文件属性配置,还支持 Java 系统属性命令行参数 的方式进行属性配置。
在这里插入图片描述

优先级: 命令行参数 > 系统属性参数 > properties 参数 > yml 参数 > yaml 参数

项目已经打包上线了,这个时候我们又如何来设置Java系统属性和命令行参数呢?
在这里插入图片描述

注意事项

  • Springboot 项目进行打包时,需要引入插件 spring-boot-maven-plugin (基于官网骨架创建项目,会自动添加该插件)
    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId>                </plugin></plugins></build>

二、Bean 管理

1 获取 Bean

默认情况下,Spring 项目启动时,会把 bean 都创建好放在 IOC 容器中,如果想要主动获取这些 bean,可以通过如下方式:

  • 根据 name 获取 bean:
    Object getBean(String name)
  • 根据类型获取 bean:
    <T> T getBean(Class<T> requiredType)
  • 根据 name获取 bean(带类型转换):
    <T> T getBean(String name, Class<T> requiredType)

上述所说的 【Spring 项目启动时,会把其中的 bean 都创建好】还会受到作用域及延迟初始化影响,这里主要针对于 默认的单例非延迟加载的 bean 而言。

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {@Autowiredprivate ApplicationContext applicationContext; //IOC容器对象//获取bean对象@Testpublic void testGetBean(){//根据bean的名称获取DeptController bean1 = (DeptController) applicationContext.getBean("deptController");System.out.println(bean1);//根据bean的类型获取DeptController bean2 = applicationContext.getBean(DeptController.class);System.out.println(bean2);//根据bean的名称 及 类型获取DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);System.out.println(bean3);}
}

2 Bean 作用域

Spring 支持五种作用域
在这里插入图片描述

可以通过 @Scope 注解来进行配置作用域:

//@Lazy
@Scope("prototype")
@RestController
@RequestMapping("/depts")
public class DeptController {
}

注意事项:

  • 默认 singleton 的 bean,在容器启动时被创建,可以使用 @Lazy 注解来延迟初始化(延迟到第一次使用时)。
  • prototype 的 bean,每一次使用该 bean 的时候都会创建一个新的实例。
  • 实际开发当中,绝大部分的 Bean 是单例的,也就是说绝大部分 Bean 不需要配置 scope 属性。
@SpringBootTest
class SpringbootWebConfig2ApplicationTests {@Autowiredprivate ApplicationContext applicationContext; //IOC容器对象//bean的作用域@Testpublic void testScope(){for (int i = 0; i < 10; i++) {DeptController deptController = applicationContext.getBean(DeptController.class);System.out.println(deptController);}}
}

3 第三方 Bean

如果要管理的 bean 对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明 bean 的,就需要用到 @Bean 注解。

解决方案1:在启动类上添加 @Bean 标识的方法(不建议,项目中要保证启动类的纯粹性)

@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}//声明第三方bean@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器beanpublic SAXReader saxReader(){return new SAXReader();}
}
@SpringBootTest
class SpringbootWebConfig2ApplicationTests {@Autowiredprivate ApplicationContext applicationContext; //IOC容器对象@Autowiredprivate SAXReader saxReader;//第三方bean的管理@Testpublic void testThirdBean() throws Exception {//SAXReader saxReader = new SAXReader();Document document = saxReader.read(this.getClass().getClassLoader().getResource("1.xml"));Element rootElement = document.getRootElement();String name = rootElement.element("name").getText();String age = rootElement.element("age").getText();System.out.println(name + " : " + age);}
}

解决方案2:在配置类中定义 @Bean 标识的方法

  • 若要管理的第三方 bean 对象,建议对这些 bean 进行集中分类配置,可以通过 @Configuration 注解声明一个配置类。
@Configuration //配置类
public class CommonConfig {//声明第三方bean@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean//通过@Bean注解的name/value属性指定bean名称, 如果未指定, 默认是方法名public SAXReader reader(DeptService deptService){System.out.println(deptService);return new SAXReader();}}

注意事项:

  • 通过 @Bean 注解的 name 或 value 属性可以声明 bean 的名称,如果不指定,默认 bean 的名称就是方法名。
  • 如果第三方 bean 需要依赖其它 bean 对象,直接在 bean 定义方法中设置形参即可,容器会根据类型自动装配。

@Component 及衍生注解 与 @Bean 注解使用场景?

  • 项目中自定义的,使用 @Component 及其衍生注解
  • 项目中引入第三方的,使用 @Bean 注解

三、SpringBoot 原理

在这里插入图片描述
通过 SpringBoot 来简化 Spring 框架的开发(是简化不是替代)。我们直接基于 SpringBoot 来构建 Java 项目,会让我们的项目开发更加简单,更加快捷。

在这里插入图片描述

  • 通过 SpringBoot 所提供的起步依赖,就可以大大的简化 pom 文件当中依赖的配置,从而解决了 Spring 框架当中依赖配置繁琐的问题。
  • 通过自动配置的功能就可以大大的简化框架在使用时 bean 的声明以及 bean 的配置。我们只需要引入程序开发时所需要的起步依赖,项目开发时所用到常见的配置都已经有了,我们直接使用就可以了。

1 起步依赖

为什么我们只需要引入一个 web 开发的起步依赖,web 开发所需要的所有的依赖都有了呢?

  • 因为 Maven 的依赖传递。
  • 在 SpringBoot 给我们提供的这些起步依赖当中,已提供了当前程序开发所需要的所有的常见依赖(官网地址:https://docs.spring.io/spring-boot/docs/2.7.7/referen
    ce/htmlsingle/#using.build-systems.starters )。
  • 比如:springboot-starter-web,这是 web 开发的起步依赖,在 web 开发的起步依赖当中,就集成了 web 开发中常见的依赖:json、web、webmvc、tomcat等。我们只需要引入这一个起步依赖,其他的依赖都会自动的通过 Maven 的依赖传递进来。

结论:起步依赖的原理就是 Maven 的依赖传递。

2 自动配置

2.1 概述

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

2.2 方案一,@ComponentScan 组件扫描

@ComponentScan({"com.example","com.itheima"})
@SpringBootApplication
public class SpringbootWebConfig2Application {
}

缺点:

  1. 使用繁琐
  2. 性能低

2.3 方案二,@Import 导入

使用 @Import 导入的类会被 Spring 加载到 IOC 容器中,导入形式主要有以下几种:

  1. 导入 普通类
  2. 导入 配置类
  3. 导入 ImportSelector 接口实现类
  4. @EnableXxxx 注解,封装 @Import 注解(第三方依赖自己指定)
//@Import({TokenParser.class})//导入普通类,交给IOC容器管理
//@Import({HeaderConfig.class})//导入配置类,交给IOC容器管理
@Import({MyImportSelector.class})//导入ImportSelector接口实现类,交给IOC容器管理
@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}
}
public class MyImportSelector implements ImportSelector {public String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.example.HeaderConfig"};}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig {
}
@EnableHeaderConfig
@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}
}

2.4 原理分析

2.4.1 源码跟踪

在这里插入图片描述
@SpringBootApplication
该注解标识在 SpringBoot 工程引导类上,是 SpringBoot 中 最最最重要 的注解。该注解由三个部分组成:

  1. @SpringBootConfiguration:该注解与 @Configuration 注解作用相同,用来声明当前也是一个配置类。
  2. @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包。
  3. @EnableAutoConfiguration:SpringBoot 实现自动化配置的核心注解。

在这里插入图片描述

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

在这里插入图片描述

@Configuration
public class HeaderConfig {@Bean@ConditionalOnClass(name = "io.jsonwebtoken.Jwts")// 环境中存在指定的这个类,才会将该bean加入IOC容器public HeaderParser headerParser1(){return new HeaderParser();}@Bean
//    @ConditionalOnMissingBean //当不存在当前类型(HeaderGenerator)的bean时,才声明该bean
//    @ConditionalOnMissingBean(name = "deptController2") //不存在指定名称的bean,才会将该bean加入IOC容器@ConditionalOnMissingBean(HeaderConfig.class)//不存在指定类型的bean,才会将bean加入IOC容器public HeaderGenerator headerGenerator(){return new HeaderGenerator();}@Bean@ConditionalOnProperty(name = "name" ,havingValue = "itheima")//配置文件中存在指定的属性与值,才会将该bean加入IOC容器public HeaderParser headerParser2(){return new HeaderParser();}}

2.5 案例

2.5.1 自定义 starter 分析

场景
在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在 SpringBoot 的项目中,一般会将这些公共组件封装为 SpringBoot 的 starter。

  • SpringBoot 官方 starter 命名: spring-boot-starter-xxxx
  • 第三组织提供的 starter 命名: xxxx-spring-boot-starter
    在这里插入图片描述
2.5.2 自定义 starter 实现

需求

  • 自定义 aliyun-oss-spring-boot-starter,完成阿里云 OSS 操作工具类 AliyunOSSUtils 的自动配置。
  • 目标:引入起步依赖引入之后,要想使用阿里云OSS,注入 AliyunOSSUtils直接使用即可。

步骤

  1. 创建 aliyun-oss-spring-boot-starter 模块
  2. 创建 aliyun-oss-spring-boot-autoconfigure 模块,在 starter 中引入该模块
  3. 在 aliyun-oss-spring-boot-autoconfigure 模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/xxxx.imports
    在这里插入图片描述
    (1)在 aliyun-oss-spring-boot-autoconfigure 模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/xxxx.imports

在 SpringBoot 项目中,并不会去扫描 com.aliyun.oss 这个包,所以注释 @Component 注解。

@Data
//@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
  • @Configuration 标识该类为配置类
  • @EnableConfigurationProperties 底层为 @Import
//@Component
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class)
public class AliOSSAutoConfiguration {@Beanpublic AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){AliOSSUtils aliOSSUtils = new AliOSSUtils();aliOSSUtils.setAliOSSProperties(aliOSSProperties);return aliOSSUtils;}
}

在 aliyun-oss-spring-boot-autoconfigure 模块中的 resources 下,新建自动配置文件:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.impo
rts

com.aliyun.oss.AliOSSAutoConfiguration 
http://www.lryc.cn/news/324467.html

相关文章:

  • ChatGPT论文指南|揭秘8大ChatGPT提示词研究技巧提升写作效率【建议收藏】
  • P1563 [NOIP2016 提高组] 玩具谜题
  • 【数据库】数据库语言
  • javascript单例模式字面量定义的接口和匿名函数定义的接口;他们之间访问私有变量和私有函数之间的区别
  • 啥是大语言模型LLM
  • vue3之路由导航故障
  • Dr4g0n
  • 蓝桥杯每日一题:扫雷
  • net core API 后台系统操作日志的实现思路
  • ORACLE 知识整理
  • 业务服务:redisson
  • 面试算法-100-零钱兑换
  • 【Leetcode每日一题】 动态规划 - 使用最小花费爬楼梯(难度⭐)(41)
  • Springboot旅游管理系统设计与实现
  • c++学习笔记(10)
  • Visual Studio - 添加快捷键图标
  • 突破边界:Web3开启数字化社会的新纪元
  • docker仓库登录及配置insecure-registries的方法
  • Lambda函数与Selenium WebDriverWait类一起使用
  • V R元宇宙平台的未来方向|V R主题馆加 盟|游戏体验馆
  • sox命令用法
  • Android kotlin全局悬浮窗全屏功能和锁屏页面全屏悬浮窗功能二
  • [数据结构]二叉树与递归OJ
  • vue iframe实现父页面实时调用子页面方法和内容,已解决
  • Spring Cloud Gateway教程
  • 解码新时代内存架构:探秘数据在内存中的灵动驻足
  • 前端基础篇-前端工程化 Vue 项目开发流程(环境准备、Element 组件库、Vue 路由、项目打包部署)
  • 【通用人工智能AGI元年-各领域的精彩AI/LLM(持续更新)】
  • 【微服务】设计弹性微服务架构模式
  • Websocket + Vue使用