SpringBoot

type
Post
status
Published
date
Apr 14, 2025
slug
springboot
summary
tags
category
Java Web
icon
password
Parent item
Sub-item
Place

Spring

IOC

IOC:控制反转,在传统开发过程中,如果我们要使用一个对象,我们需要手动new一个对象,这样耦合性太高,IOC的核心是将对象的创建、组装以及生命周期的管理从程序代码转移到外部容器(Spring),而Spring帮我们实现了这一过程,我们只需要声明和使用即可。

DI

依赖注入
当一个类需要依赖另一个类的对象时,就必须在类中直接new这个类的对象,这样耦合性太高了,依赖注入指的是将对象的创建和依赖关系的管理交给Spring容器来实现,类只需要声明要依赖的对象即可,Spring容器会在允许是将依赖对象注入到类中,降低耦合度

AOP

指的是面向切面编程,他允许我们在不修改原来代码的情况下,对其进行逻辑增强。
他的实现是依赖于动态代理,即JDK动态代理和CGlib动态代理,如果target实现了接口,就用JDK动态代理,如果没有,就用CGlib动态代理
这两个的区别就是JDK动态代理中代理类是实现了相同的接口,并且代理类中含有目标类对象,在调用目标类方法前后进行逻辑增强。CGlib动态代理是继承了目标类,通过重写方法进行逻辑增强
主要概念:(这考那就是sb了,上面的足够了)
  1. Aspect:切面
  1. Pointcut:切点
  1. Advice:通知
  1. Joint point:连接点
  1. target:目标对象
  1. AOP proxy:代理对象

考虑过AOP的性能问题嘛?

在实际生产AOP 的性能开销通常是纳秒级或微秒级的。
相比于它代理的业务逻辑(比如数据库 IO、网络请求、复杂计算),AOP 本身的损耗几乎可以忽略不计。除非是在极度追求性能的高频计算场景(比如每秒百万次调用的纯内存计算),否则我们不认为 AOP 是性能瓶颈。

事务

编程式事务
声明式事务(一般使用的,基于注解和AOP来声明)
实际调用的是代理类中的invoke方法
  1. 事务只用作用到public方法上才生效
  1. 底层的数据库必须支持事务(myisam就不行)
  1. propagation(传播):事务传播行为
      • REQUIRED(required,必须的,默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
      • REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说无论如何都会创建新的事务,且相互独立,互不影响。
      • SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
      • NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起
      • MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
      • NEVER:以非事务方式运行,如果当前存在事务,则抛出异常
      • NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行
  1. isolation:事务隔离级别
      • DEFAULT(默认):使用底层数据库的默认隔离级别
      • READ_UNCOMMITTED:读未提交
      • READ_COMMITTED:读已提交
      • REPEATABLE_READ:可重复读
      • SERIALIZABLE:串行化
  1. timeout:事务超时时间(秒)
  1. readOnly:是否只读事务(默认为false)
  1. rollbackFor/rollbackForClassName:指定哪些异常触发回滚
  1. noRollbackFor/noRollbackForClassName:指定哪些异常不触发回滚
说明:
  1. 这个事务配置表示:
      • 使用REQUIRED传播行为(默认值,可省略)
      • 使用READ_COMMITTED隔离级别
      • 超时时间为30秒
      • 非只读事务(默认值,可省略)
      • 遇到BusinessException或SQLException会回滚
      • 遇到IllegalArgumentException不会回滚
  1. placeOrder方法被调用时,Spring会开启一个事务,如果方法正常执行完成,事务会被提交;如果抛出BusinessException或SQLException,事务会被回滚;如果抛出IllegalArgumentException,事务不会回滚。
  1. 如果paymentService.processPayment()也使用了事务注解,根据传播行为的不同,可能会加入当前事务或开启新事务。

循环依赖

  1. 构造方法产生的循环依赖问题
  1. setter方法,且对象是原型
  1. setter方法,对象是单例模式
Spring只解决了第3种情况下的
1级缓存存储的是完全好的
2级缓存存储的是实例化,但还未属性填充的
3级缓存存储的是工厂对象
image-20250412111530343
image-20250412111530343
image-20250412111530343

Bean的生命周期

  1. 实例化(Instantiation)
  1. 属性赋值(Populate)
  1. 初始化(Initialization)
  1. 使用
  1. 销毁(Destruction)
实例化:指的是为Bean分配内存空间,实例化一个Bean对象。这里如果Bean是个单例模式的化,会判断容器中是否已经存在了这个对象,如果有的话直接取出来使用
属性赋值:为Bean的属性进行赋值和依赖注入(循环依赖问题就是发生在这个阶段)
初始化:执行各种通知和初始化方法,这里通过BeanPostProcessorAware接口提供了大量扩展点
使用Bean
销毁Bean:执行销毁Bean对象的操作

SpringBoot

简单介绍一下SpringBoot

  1. 默认集成了多种内嵌服务器,比如说tomcat,Jetty
  1. 简化开发:SpringBoot采用了自动配置的机制,根据程序中引入的依赖和配置,SpringBoot可以自动配置整个应用程序的环境,大大减少了开发者需要进行的手动配置操作
  1. 快速启动:SpringBoot快速的项目启动器,通过引入不同的starter,可以快速集成需要的框架爱和库
  1. 遵循约定大于配置的原则,提高了一系列默认的配置和约定,如果开发者按照这些约定开发,可以大大减少配置文件的编写,可以更加专注于业务代码的实现。

SpringBoot自动装配原理

  1. SpringBoot项目中的启动类上有一个@SpringBootAplicatioon,他对3个注解进行了封装
  1. SpringBootConfiguratiion
  1. EnableAutoConfiguration
  1. ComponentScan
  1. 其中EnableAutoConfiguration使实现自动装配的核心
  1. 他里面有一个import注解,通过他我们先从spring.factories文件中获取获取候选配置类。
  1. 排除不满足当前环境的配置类。
  1. 利用有效的配置类 按需实例化这些 Bean

常用注解

按照程序启动来思考
  1. SpringBootAplicatioon,用于标识应用程序的入口点
  1. Controller:标明控制器类
  1. Service:表明服务类
  1. Autiwired:自动注入
  1. Configuration:标明是一个配置类
  1. RequestMapping:映射HTTP请求到Controller的方法上
  1. 类似的有GetMapping,DeleteMapping等等

MyBatis-plus

背这个表就行
维度
MyBatis
MyBatis-Plus
SQL 编写
必须手动编写(XML 或注解),哪怕是简单的 selectById
通过BaseMapper,单表 CRUD 无需编写 SQL。
动态 SQL
使用 XML 标签如 <if>, <where>, <foreach>
提供 Wrapper 条件构造器,复杂的条件查询
分页插件
通常需引入第三方 PageHelper
自带分页插件,通过配置 Interceptor 即可实现。
功能扩展
需自行扩展(如逻辑删除、自动填充)。
内置逻辑删除 (@TableLogic)、自动填充、序列化插件等。
第一个就是mybatis通过BaseMapper使得单表的CRUD无需编写SQL,直接调用函数即可。第二就是提供了wrapper条件构造器,支持复杂的条件查询。第3个就是新增了注解,可以将实体类和数据库表对应,以及字段与列对应。除此之外还支持分页等等

BaseMapper

正如你所说,MyBatis 需要你为每一个简单的增删改查(CRUD)编写 SQL(通常在 XML 中)。而 MyBatis-Plus 通过 BaseMapper<T> 接口,将这些操作封装成了 Java 函数。
  • MyBatis: 你需要定义接口,并在 XML 中写 SELECT * FROM user WHERE id = #{id}
  • MyBatis-Plus: 你的 Mapper 只需要继承 BaseMapper<User>,就可以直接调用 userMapper.selectById(1)
原理: MP 在启动时会根据你的实体类(Entity)信息,自动生成注入这些基础的 SQL 语句。

具体示例

方法名
说明
对应SQL
insert(T entity)
插入
INSERT INTO…
deleteById(Serializable id)
按ID删除
DELETE FROM…WHERE id=…
updateById(T entity)
按ID更新
UPDATE…WHERE id=…
selectById(Serializable id)
按ID查询
SELECT * FROM…WHERE id=…
selectBatchIds(Collection ids)
批量ID查询
SELECT * FROM…WHERE id IN…
selectList(Wrapper wrapper)
条件查询
SELECT * FROM…WHERE…
selectPage(Page page, Wrapper wrapper)
分页查询
SELECT * FROM…LIMIT…

新增注解

你提到的“实体类加注解”是 MP 实现自动化 SQL 的基础。
  • @TableName: 指定实体类对应的数据库表名。
  • @TableId: 指定主键,并可以配置主键生成策略(如雪花算法、自增等)。
  • @TableField: 处理字段名与数据库列名不一致的情况,或者排除非数据库字段。
这种方式极大地减少了 ResultMap 的配置工作,让代码更加整洁。

Wrapper

这是 MP 的灵魂。它允许你通过 Java 代码动态构建复杂的 WHERE 条件,而不需要在 XML 里写大量的 <if> 标签。

内置的分页插件

  • MyBatis: 通常需要引入 PageHelper 插件。
  • MyBatis-Plus: 自带分页插件,你只需要配置一个 Interceptor,然后在代码里传一个 Page 对象即可。

自动填充与逻辑删除

  • 自动填充: 比如 create_timeupdate_time,可以通过配置在插入或更新时自动赋值,不需要手动 set
  • 逻辑删除: 只需一个 @TableLogic 注解,delete 操作就会自动变成 update set deleted = 1,查询时也会自动过滤掉已删除数据。

ThreadLocal

1.什么是ThreadLocal

ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
从源码上看,Thread 类中有一个成员变量 ThreadLocalMap。ThreadLocal 仅仅是作为一个入口Key。 当执行 threadLocal.set(value) 时,它会分三步走:
  1. 首先获取 Thread.currentThread()
  1. 然后拿到该线程对象的 ThreadLocalMap
  1. 最后以 ThreadLocal 对象自身为 Key,将 value 存入这个 Map。
取值的时候也是同理,通过当前 ThreadLocal 对象去当前线程的 Map 里查。既然 Map 是属于线程私有的,自然就实现了物理上的隔离。”

other(了解)

.gitgnore:

git需要忽略的配置文件

AOP示例代码

切面类
target类,不需要任何修改
概念
  1. Aspect:指的是LogAspect这个类
  1. Pointcut:指的是定义什么时候代理
  1. Advice:做了什么增强的逻辑
  1. Joint point:被代理的地方都叫
  1. target:目标对象
  1. AOP proxy:转化后的代理对象,我们看不到的
上一篇
How to create a MCP Server
下一篇
The clever use of search engines
Loading...