Springboot 原理 及源码解析

Springboot配置优先级

场景:当我们通过多种配置配置了同一个属性时,哪一个配置优先生效

配置文件

 .properties   .yml     .yaml

通过测试:优先级分别为: .properties >  .yml > .yaml

企业主流配置方式: .yml

java系统属性和命令行参数

优先级:命令行参数 > java系统属性

如何在jar包运行前调整配置属性

方法:在运行jar包的指令前,输入java系统属性,在jar包运行命令之后加入命令行指令

Maven打包

在打包命令时遇到一个错误提示,导致项目打包失败

根据其指定的目录位置,找到测试报告后并分析,发现是由于JWT令牌过期引起的

出错的测试是 tlias.TliasApplicationTests.getjwt 方法,错误类型是 io.jsonwebtoken.ExpiredJwtException,这意味着尝试解析的 JWT(Json Web Token)已经过期。JWT 在 2024 年 8 月 21 日 02:00:42 UTC 过期,而当前时间是 2024 年 8 月 28 日 05:30:26 UTC,过期时间为 617,384,466 毫秒。此外,系统不允许任何时钟偏移(Allowed clock skew: 0 milliseconds),也就是说即使 JWT 过期一点点也不能接受。

错误发生在 TliasApplicationTests.java 文件的第 40 行,这是调用 getjwt 方法的地方。根据堆栈跟踪,问题出现在 JWT 解析的过程中。

要解决这个问题,可以采取以下步骤:

  1. 更新 JWT:如果 JWT 是用于测试的,那么应该更新 JWT 以使其有效,或者创建一个新的 JWT 用于测试目的。

  2. 允许时钟偏移:如果可以的话,在解析 JWT 时允许一定的时钟偏移。这通常通过配置 JWT 解析器实现,允许一个小的时间窗口来弥补不同系统之间的时间同步差异。

  3. 检查 JWT 配置:确认 JWT 的配置是否正确,特别是有关过期时间和时钟偏移的部分。

  4. 模拟 JWT:为了防止在测试中使用真实的 JWT 可能带来的问题,可以考虑使用模拟数据来代替真实的 JWT,这样可以避免因为 JWT 过期导致的测试失败。

  5. 隔离测试环境:确保测试环境中的 JWT 仅用于测试,并且不会影响到生产环境中的 JWT 使用情况

运行jar包时配置属性

1.在jar包所在的文件目录下打开cmd

2.如果忘记了运行jar包的java命令,在命令窗口输入java,回车,即可查看常用命令

由此提示可知

java系统属性要写在 -jar 命令之前,命令行参数要写在 -jar 命令之后

全部的配置优先级顺序

命令行参数 > java系统属性 > .properties >  .yml > .yaml


Bean 管理

获取Bean对象

获取方式

通过依赖注入的方式,获取IOC容器的对象。然后调用其中的方法获取Bean对象

通过控制台的输出,发现得到的Bean对象时同一个

原因:Spring中默认的Bean都是单例的,也就是只会有一个Bean对象。可以通过作用域修改。


Bean的作用域

作用域的分类

注:主要研究前两种作用域,后三种不常用。

Spring默认创建Bean的情况:

       在Spring项目构建时,就创建好了Bean对象,而且只会创建一次,后续用到Bean的时候,用的都是同一个Bean对象。

@Lazy注解

        介绍:通过这个注解,可以使Bean在第一次需要构建时再被构建出来,而不是在项目构建时就构架出来。也就是会延迟初始化。

        注意:但是该对象还是只能创建一次,后续用到Bean时用到的都是延迟初始化创建的Bean对象。

@Scope(“作用域名称”)注解

介绍:通过这个注解,可以设置Bean的作用域

例: 设置作用域为非单例的

运行程序结果:得到了不同地址值的Bean


第三方Bean的配置

使用场景:

使用第三方Bean时,由于每次使用都需要创建Bean对象,耗时且浪费资源。想将第三方Bean交给IOC容器管理,用到时直接依赖注入,但是无法手动在第三方Bean上面加注解将其交给IOC容器管理。

@Bean注解

介绍:

通过@Bean注解可以把第三方Bean交给IOC容器管理

使用方法:

        1.在启动类中,声明一个方法,返回值类型就是第三方Bean,然后方法体返回一个new出来的第三方Bean对象。并在该方法上加@Bean注解,即表示将这个对象交给IOC容器管理(不建议使用这种方式)

注意:但是不建议使用这种方法进行配置,因为启动要简洁,一般只用于启动项目。

        2.定义一个配置类,其余操作同上。所有的第三方Bean都可以在这个类中统一交给IOC容器管理。


SpringBoot原理

最基础的框架:Spring Framework

Springboot 简单的主要原因:

        底层帮我们提供了两个功能: 起步依赖,自动配置

起步依赖: 大大简化pom文件中依赖的配置。通过Maven的依赖传递,封装了许多依赖,简化了依赖配置。

自动配置:大大简化框架使用时Bean的声明和配置。


自动配置原理(面试高频)

研究方向:        在Springboot中引入依赖后,是如何将依赖jar包中所定义的配置类,Bean加载Spring的IOC容器当中的。

pom文件:      我们在pom文件中引入的都是依赖的坐标。如果这个坐标在Maven的仓库里有,联网情况下IDEA就可以自动联想和下载。如果引入的依赖不在Maven仓库里,就需要我们把依赖导入到项目中,然后再到依赖里输入依赖的坐标,就可以引入依赖。

将Bean交给IOC管理的条件:

                1.有Conponent注解或其衍生注解

                2. 包被启动类扫描

启动类的默认扫描范围:启动类所在包及其子包。

问题:如果我们自己引入第三方包,不在该包中,就不会被扫描到

解决方案:

1.通过@ComponentScan注解指定需要扫描的包

缺点: 使用繁琐,每一个要扫描的包都得自己指定

            性能低,包下出了Bean类等需要扫描的包外有其实有许多包本来是不需要扫描的。

2.通过@import 注解指定需要导入的类

示例如下:

3.第三方提供@EnableXxxx注解 

注意:该注解底层封装了import注解

让第三方依赖自己指定要加载到IOC容器的类,底层封装了@import注解,让第三方自己指定要导入哪些配置类。我们再启动类上加第三方提供的这个注解即可。

启动类:

自定义注解类:

自定义注解里指定的配置类:


启动类源码分析:

分析对象:启动类的@SpringBootApplication注解

@SpringBootApplication注解的组成

1.定义注解的源注解:@Target   @Retention  @Document  @Inherited

                  翻译分别为: 目标,       保留,         文档,        继承,可以用于大概猜测注解含义。

2.@SpringBootConfiguration注解

该注解的源码如下,包含了一个@Configuration注解,表明这是一个配置类

注:这也解释了之前为什么我们可以在启动类中利用@Bean注解将对象交给IOC容器管理。

3.@ComponentScan注解

该注解是包扫描注解,指定了这个启动类要扫描哪些包。其中的@Filter 注解主要用于配置 @ComponentScan 的排除规则,确保在组件扫描过程中不会包含不需要的类。

4.@EnableAutoConfiguration注解

@EnableXxxx注解底层一般是@import注解,用于导入指定的Bean或者是配置类。

源码的持续跟进

@Import 注解里传递的是@ImportSelector接口的实现类

其实现的接口中的第一个接口@DeferredImportSelector就是继承了@ImportSelector

@ImportSelector接口内有一个最重要的方法

方法返回值String类型的数组,封装的就是哪些类需要导入到IOC容器,

里面封装的就是这些类的全类名

所以我们再回到它的实现类,也就是AutoConfguration注解里面,找到它重写的lselectImport方法

现在,我们只需要找到这个方法返回的String类型数组中包含了哪些全类名,就可以知道它会把哪些类交给IOC容器管理了

通过方法体,大致可以判断,返回的全类名是由这个方法getAutoConfigurationEntry得到的

方法的返回值是 new AutoConfigurationEntry (),传递的参数有一个Configurations,这是一个List集合,现在的重点就是看这个configurations究竟封装了哪些对象。这个集合是由这个方法得到的,所以要进入这个方法查看。

同理,通过源码可知,我们要查看创建ArrayList中传递参数时调用的这个方法SpringFactoriesLoader.loadFactoryNames

这个方法的参数列表显示,传递的两个参数时Class类型的,后面就是把这两个参数进行处理后强转成List类型返回,所以我们需要看下这两个参数是什么,factoryType,classLoader

factoryType

以及最后强转为list的那个方法都提到了一个文件META-INF/spring.factories

虽然再往下代码看不懂了,但是查资料得知,Springboot就是在启动时会扫描这个文件”META-INF/spring.factories”,然后吧这个文件里的信息加载到String集合当中。然后又因为之前提到的配置类注解和@Import注解,所以会把这个文件当中包括的类都交给IOC容器管理。

关于   META-INF/spring.factories   文件

所有我们引入的依赖的配置文件中,都有这么一个文件,用于自动配置

例如Springframework中是这样的,这个就是自动配置的依赖,其中就包含这个文件

在IDEA的外部库里,可以查看所有我们引入的jar包内容

打开Springframework的jar包,可以找到这个文件

打开这个文件,发现里面全都是全类名。这份文件最终会被读取出来,加载到IOC容器当中,交给IOC容器管理。

另外一个文件,也是同样的用处,这个是后面版本提供的配置类方案,在新版本的Springboot中,配置文件都会存放在这个配置类中,而spring.factories是老版本的,也会兼容。但嘴型版本的Springboot中,将会完全使用org.springframework.boot.autoconfigure.AutoConfiguration.imports,这个文件来进行自动配置。


@Conditional注解:

用途:

配置文件中有那么多的全类名,难道全部都会注册到IOC容器当中吗?是不是也存在一些不需要注册到IOC容器当中的类呢,那么又该如何将其排除掉呢?

这时候就需要用到我们的这个注解了。

介绍:

使用场景:

加在方法或类上,指定该方法在什么条件下才会被注册到Bean的IOC容器中

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值