0 Pojo类
前端给后端:DTO
后端给前端:VO
数据库:PO/VO
业务处理逻辑:BO
统称pojo
1 代理模式
实现静态代理:
- 1定义接口
- 2实现类
- 3写一个静态代理类
- 4这样在调用时就可以使用这个静态代理类来实现某些功能
实现动态代理
- 1实现接口
- 2实现类
- 3写一个动态代理模块
- 4可以使用通用方法(直接强转)
- 实现AOP切面编程
2 事务
事务四大特性(ACID)
-
原子性
-
定义:事务是最小操作单元,要么全部成功,要么全部失败回滚。
-
关键点:不存在“部分成功”,如转账时扣款和加款必须同时完成或撤销。
-
-
一致性
-
定义:事务完成后,数据必须满足业务规则(如账户余额不为负)。
-
关键点:通过原子性、隔离性、持久性共同保障最终一致性。
-
-
隔离性
-
定义:并发事务之间互不干扰,避免脏读、不可重复读、幻读。
-
关键点:通过隔离级别(如
READ_COMMITTED
)控制并发影响。
-
-
持久性
-
定义:事务提交后,数据永久保存,即使系统故障也不丢失。
-
关键点:依赖数据库持久化机制(如日志、磁盘存储)。
-
事务隔离问题与解决方案
-
脏读
-
现象:读到其他事务未提交的数据(若事务回滚则数据无效)。
-
解决:
READ_COMMITTED
级别,仅读取已提交的数据。
-
-
不可重复读
-
现象:同一事务多次读取同一数据,结果不一致(因其他事务修改)。
-
解决:
REPEATABLE_READ
级别,锁定已读数据禁止修改。
-
-
幻读
-
现象:同一事务中查询结果集数量变化(因其他事务增删数据)。
-
解决:
SERIALIZABLE
级别,锁定整表禁止增删。
-
事务管理方式
-
声明式事务
-
实现:通过
@Transactional
注解或 XML 配置。 -
优点:代码简洁,无侵入性。
-
缺点:调试困难(异常可能被代理包装)。
-
-
编程式事务
-
实现:手动编码控制事务(如
TransactionTemplate
)。 -
优点:灵活,可精细控制事务边界。
-
缺点:代码冗余,侵入性强。
-
Spring 开启事务的步骤
-
启用事务管理
-
在配置类添加
@EnableTransactionManagement
,启用注解驱动事务。
-
-
配置事务管理器
-
定义
PlatformTransactionManager
Bean(如DataSourceTransactionManager
)。
-
-
标记事务方法
-
在 Service 方法或类上添加
@Transactional
,指定隔离级别、传播行为等属性。
-
3 IOC/MVC/AOP三个概念在Spring中的理解
IOC(控制反转)Inversion of Control
核心思想:将对象的创建和依赖管理权交给 Spring 容器,实现解耦。
-
控制:对象创建的控制权。
-
反转:从手动
new
对象,转为由容器自动注入(如@Autowired
)。
实现方式: -
依赖注入(DI)Dependency Injection:通过构造函数、Setter 方法或注解自动装配依赖。
-
容器管理:Spring IoC 容器(如
ApplicationContext
)负责对象的生命周期和依赖关系。
通俗类比:
点外卖时,你只需下单(声明需要什么对象),平台(Spring 容器)负责调度餐厅(创建对象)和配送(注入依赖)。
MVC(Model-View-Controller)
核心思想:分离业务逻辑、数据和显示,提升代码可维护性。
-
Model(模型):封装业务数据和逻辑(如
Service
、DAO
层)。 -
View(视图):负责数据展示(如 JSP、Thymeleaf 模板)。
-
Controller(控制层):接收请求,调用模型处理,返回视图(如
@Controller
注解的类)。
Spring MVC 流程:
-
用户请求 → DispatcherServlet(前端控制器)
-
根据 URL 路由 → 调用对应 Controller
-
Controller 调用 Service 处理业务 → 返回数据(Model)
-
ViewResolver 解析视图 → 渲染结果返回用户。
通俗类比:
Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
餐厅中,服务员(Controller)接收订单,交给厨师(Model)做菜,最后由传菜员(View)端给顾客。
AOP(面向切面编程)Aspect Oriented Programming
核心思想:将横切关注点(与业务无关,日志,事务等)从核心业务中分离出来,形成一个个的切面,实现模块化,减少代码冗余。
实现技术:
-
动态代理(Spring AOP 默认):
-
JDK 动态代理:基于接口生成代理对象(要求目标类实现接口)。
-
CGLIB 代理:通过继承生成子类代理(可代理无接口的类)。
-
-
日志记录、事务管理(
@Transactional
)、权限校验、性能监控。
通俗类比:
咖啡师(核心业务)专注做咖啡,助手(切面)自动处理记录订单、清洁机器等杂务。
JDK动态代理:
是去动态的生成一个代理对象,其中有一个操作类Proxy,方法newProxyInstance
三个参数:
1 类加载器ClassLoader:目的将动态代理的对象加载到我们的JVM虚拟机
2 接口的集合:指的是我们要代理哪一个接口(这也是我们动态代理的一个特征,只能基于我们的接口去代理)
3 invocationHandler代理拦截(拦截器)当需要调用动态代理的一个对象的方法的时候,会走到代理器当中invoke方法,(代理的对象,调用的方法的名字,参数)传递过来,在方法中添加需要添加的代理方法实现动态代理的过程
三者的协作关系
-
IOC 容器:管理所有对象(包括 MVC 的 Controller、Service 和 AOP 的代理对象)。
-
MVC:处理 Web 请求时,依赖 IOC 容器注入 Service 和 Dao。
-
AOP:通过代理对象增强 Service 层方法(如添加事务),而这一切由 IOC 容器动态组装。
4 @Component注解与@Bean注解
@Component注解是作用在类上的,通过@Component注解Spring会自动创建该类的实例注入到SpringIOC容器中,
@Bean注解是用于配置类中声明一个Bean的,通常是用在配置类的方法上,表示把这个方法的返回对象注册到SpringIOC容器当中,通过这个注解我们可以自定义Bean的创建和初始化过程,包括指定Bean的名称、作用域、依赖关系等
核心区别
1. 用途不同:@Component通常用于标识一个普通的类,而@Bean用于配置类中的Bean对象,通常结合@Configuration进行使用。
2. 使用方式不同:@Component是类级别的注解,Spring可以扫描到被此注解标注的类并把它们注入到Spring容器中。@Bean是修饰在方法上的,表示此方法返回一个Bean对象注入到Spring容器中。
3. 控制权不同:@Component标注的类是由Spring框架来统一管理和创建的,而@Bean允许开发人员手动控制Bean的创建和配置。
5 Spring推荐使用构造器注入的原因
1 依赖完整性:确保所有必须依赖在对象创建时就被注入,避免了空指针异常的风险。
2 不可变性:有助于创建不可变对象(支持final字段),提高了线程安全性。
3 初始化保证:组件在使用前就已完成了初始化,减少了潜在的错误。
4 测试遍历性:在单元测试中可以通过构造函数传入模拟的依赖项,而不必依赖Spring 容器进行注入
依赖注入的选择策略
-
强制依赖:优先使用构造器注入(确保依赖非空、对象不可变、完全初始化,推荐默认使用)。
-
可选依赖:使用 Setter 注入 或配置方法(可为依赖提供默认值,支持后续重新配置,如配置项、动态代理对象)。
public class OrderService {
// 强制依赖(通过构造器注入)
private final PaymentService paymentService;
// 可选依赖(通过Setter注入)
private DiscountService discountService;
// 构造器注入(强制依赖)
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
// Setter注入(可选依赖)
public void setDiscountService(DiscountService discountService) {
this.discountService = discountService;
}
}
@RequiredArgsConstructor | 生成包含 final 或 @NonNull 字段的构造方法 |
6 SpringMVC
三层架构
1 Dao层:实现对数据库的操作
2 Service:业务层一些逻辑关系
3 Controller:处理http请求
简单的使用
声明(表明@RestController注解=@Controller+@ResponseBody这两个注解)
在传递参数时我们有两种传递方式1使用参数一一传递 2使用对应的封装对象POJO)
获取请求头@RequestHeader用这个注解提取HTTP请求传递的指定参数值
获取Cookie值@CookieValue从 HTTP 请求的 Cookie
头中获取指定名称的 Cookie 值。
url:Uniform Resource Identifier 统一资源标识符
7 Restful软件架构风格 资源表现层状态转移
Resource Representational State Transfer
核心:API的设计原则
RESTful = 用资源地址(URI) + 标准动作(HTTP方法) + 明确状态码(2xx/4xx/5xx)
用 HTTP 方法(GET/POST/PUT/DELETE 等)表示“动作”
用 URL 表示“资源” (信息)。
RESTful 的 HTTP 方法:用 GET
查、POST
增、PUT/PATCH
改、DELETE
删,动作在方法里,资源在地址里。
URL vs. HTTP 方法的分工
动作 | HTTP 方法 | URL 示例 | 说明 |
---|---|---|---|
获取所有用户 | GET | /users | 列表用复数名词 |
获取单个用户 | GET | /users/123 | 用 ID 定位单个资源 |
创建用户 | POST | /users | 资源集合 URL + POST |
更新用户 | PUT | /users/123 | 用 ID 定位 + PUT |
删除用户 | DELETE | /users/123 | 用 ID 定位 + DELETE |
客户端 → HTTP 请求(RESTful 接口) → Controller 层 → Service 层 → Dao 层 → 数据库
↑ ↑
协议处理(RESTful) 业务逻辑与数据操作(分层架构)
对比:RESTful vs 非RESTful
场景 | RESTful 示例 | 非RESTful 反例 |
---|---|---|
获取用户 | GET /users/123 | POST /getUser?id=123 |
创建订单 | POST /orders | GET /createOrder |
更新资料 | PUT /users/123 | POST /updateUser |
错误响应 | 404 Not Found | 200 OK { "code": 404 } |
8 拦截器
作用对象controller
1 定义一个类实现HandlerInterceptor接口的组件(定义基础方法)preHandke=>目标方法=>postHandle=>afterCompletion
2 再定义一个类实现WebMvcConfigurer(指定拦截路径)
9 异常
主要是利用声明式异常处理@ExceptionHandler(异常类型)对方法进行声明
但是为了方便我们可以使用全局异常处理
在类上声明@ControllerAdvice+@ResponseBoby=@RestControllerAdvice
在类上再使用@ExceptionHandler
10 数据校验
需要参数绑定(指定需要校验的数据),校验失败就会抛出异常
将异常交给全局异常处理器,编写代码将校验失败抛出的异常捕获,接收校验参数,将校验结果返回并反馈。
分组校验:
分组校验确实提供了更大的灵活性,可以根据不同的业务场景为不同的字段设置不同的校验规则
分组校验可以根据需求设置组别,比如说在登录时需要一个NotNull但是注册时不需要这个一个校验,那我们就可以在不需要的校验参数groups中不加对应的组,需要就加上组别,最后具体实现的时候在@Validdated中声明对应的组别即可实现更加灵活的校验帮我组织语言
不使用分组校验:
在类中声明时使用的是@Valid导致的是将传递的对象的参数所有都进行校验,但是使用分组校验则可以自己控制校验的数据(在自己需要校验的字段中的groups中指定即可)
在分组校验中,如果某个字段没有被指定到特定的分组,那么在使用该分组进行校验时,该字段将不会被校验。然而,这并不会影响该字段的数据传递。也就是说,即使 email 字段没有被指定到 LoginGroup 分组,email 参数仍然会正常传递到方法中,只是不会对其进行校验。
11 VO
VO(值对象)的核心作用是为前端提供安全、精简的数据视图。
我们需要根据需求设置一个不同于原先的Bean类,将需要脱敏的数据隐藏,在查询等方法的方法内部编写需要的程序,利用BeanUtils.copyProperties完成基础属性拷贝后,可针对性实现数据脱敏
12 Maven
核心配置:GAVP:GroupId、ArttifactId、Version、Packaging(scope依赖的作用范围)
生命周期:编译,运行测试,打包,安装到本地,部署到远程
- 依赖传递特性:自动引入直接依赖的间接依赖,简化配置,但可能引发版本冲突
- 依赖冲突特性:路径最近优先和声明顺序优先,先声明优先,路径短优先。
- 工程继承聚合:
-
继承:子模块复用父POM的配置(依赖/插件/版本),统一管理。
-
聚合:通过父POM的
<modules>
批量构建多个子模块,实现一键多模块协作。
父模块声明版本号即可,子模块可不声明
13 自动配置
自动配置是Spring的一大特性,其会在底层将一些配置信息自动配置。
选择starter依赖Springboot会自动引入场景的所有依赖,其会导入spring-boot-autoconfiguration自动配置包里面的文件中包含所有的配置信息
调用是通过主程序的@Adpplication注解,其包含三个注解
一个是@ComponentScan组件扫描
一个是@SpringBootConfiguration标识为配置类
一个是@EnableAutoConfiguration启动自动配置的核心开关
里面有一个@import(AutoConfigurationImportSelector.class),这里会导入自动配置类从之前的依赖导入的jar包中寻找配置信息
自动配置类XxxAutoConfiguration会根据@Conditional条件注解进行使用
自动配置类是如何配置:
自动配置类在依赖导入的jar包当中已经封装好,
配置类当中会有一个注解@EnableConfigurationProperties
会开启属性配置(属性与配置文件的绑定),属性类会从配置文件当中获取信息,
属性类当中还有一个@ConfigurationProperties注解用于获取配置文件当中配置信息进行匹配(以什么为开头)
自动配置类通常用@Configuration和@ConditionalOnXXX注解,当条件满足时,会创建相应的Bean。这些自动配置类可能依赖属性类,这些属性类通过@ConfigurationProperties绑定配置文件中的属性。
-
正确点:
-
配置信息的最终来源相同(外部配置文件)。
-
若用户未手动创建Bean,Spring自动配置生效;若用户定义Bean,优先使用用户定义。
-
-
需补充点:
-
手动配置不一定依赖属性类:开发者可以选择更灵活的配置注入方式(如
@Value
),但推荐使用属性类以保持结构化和类型安全。(@Value(“¥{指定路径进行获取})) -
自动配置强制使用属性类:这是Spring Boot设计上的一致性要求,确保配置管理的标准化。
-