目录

关于Spring的一些理解

关于Spring的一些理解

Spring整体结构:
https://i-blog.csdnimg.cn/direct/833f89baceb94daca8bc30315b142c36.png

https://i-blog.csdnimg.cn/direct/9580c8798799485d8c1068481762a4eb.png

基础

Spring启动过程

传统Spring:
(1)初始化准备阶段
(2)容器创建与注入
(3)Bean工厂后置处理
(4)Bean工厂后置处理
(5)Bean实例化与依赖注入
(6)容器启动完成
Spring Boot应用:
(1)启动类触发(@SpringBootApplication)
(2)初始化SpringApplication
(3)环境准备Environment
(4)创建ApplicationContext
(5)自动装配(@EnableAutoConfiguration)
(6)Bean加载与初始化(同传统Spring核心流程)
(7)Bean加载与初始化(同传统Spring核心流程)
(8)Bean加载与初始化(同传统Spring核心流程)

Spring的组成部分

  • 核心容器模块:核心包(spring-core)、上下文包(spring-context)、表达式语言包(spring-expression)
  • 面向切面编程模块:spring-aop、spring-aspects
  • 数据访问/集成模块:spring-jdbc、spring-tx、spring-orm
  • web模块:spring-web、spring-webmvc、spring-websocket
  • 测试模块:spring-test

Spring的优势

  • 轻量级与低侵入性
  • 强大的IoC与DI机制
  • 面向切面编程AOP
  • 丰富的模块支持
  • 良好的整合性
  • 优秀的社区支持与生态系统

Spring运用了哪些设计模式

  • 工厂模式:FactoryBean、BeanFactory和ApplicationContext
  • 单例模式:默认Bean的作用域
  • 代理模式:AOP的实现(基于JDK和CGLIB实现动态代理)
  • 模板方法模式:数据库操作模板(JDBCTemplate、RedisTemplate)
  • 观察者模式:事件驱动模型(ApplicationEvent和ApplicationListener)
  • 适配器模式:在Spring AOP中用于增强或通知(Advice)的实现。适配不同的Controller实现类
  • 装饰器模式:BeanWrapper对Bean的增强(把配置文件中的字符串转换为Bean的属性类型)
  • 策略模式:资源加载策略,ResourceLoader通过Resource接口的不同实现(ClassPathResource、FileSystemResource)

IoC

优势:解耦对象依赖、统一管理对象的生命周期、便于扩展与复用、简化测试

DI

DI与IOC的关系:

  • IOC是思想:强调“控制权转移”(容器管对象)。
  • DI是手段:通过“注入依赖”的方式,实现IOC的思想落地。

简单说:IOC 是“要解决什么问题”,DI 是“具体怎么解决”。

注入方式:构造器注入、Setter注入、字段注入

注入如何解决循环依赖问题(常见问题)

  • 三级缓存:
    • 一级缓存:用于存储已经初始化完毕的单例Bean实例
    • 二级缓存:存储已经实例化但未完成属性注入和初始化的单例Bean实例
    • 三级缓存:存储能够生成单例Bean实例的工厂对象

为什么需要三级缓存?(常见问题)

  • 依赖注入方式的选择:构造器注入(会造成死锁)、Setter注入
  • 其他解决办法:使用@Lazy注解、使用@PostConstruct注解、使用ApplicationContext获取Bean、使用接口和事件机制

Bean

如何创建Bean?

  • BeanFactory:核心接口,用于管理和提供Bean实例;
  • ApplicationContext:继承BeanFactory,有国际化、资源访问、事件传播等高级特性;
  • FactoryBean:接口,存在复杂的初始化流程时使用;
  • ObjectFactory:接口,用于延迟获取对象,常作为参数传递。

Bean的作用域(生命周期和可见范围)

  • 单例
  • 原型
  • 请求
  • 会话
  • 应用
  • webSocket会话

Bean的生命周期

  • 实例化
  • 属性复制
  • 初始化前
  • 初始化
  • 初始化后
  • 使用中
  • 销毁

单例Bean不一定线程安全怎么办?

  • 使用无状态的Bean
  • 使用线程安全容器
  • 使用同步机制
  • ThreadLocal
  • 将Scope更改为多例

初始化过程

  1. Bean定义信息的载入与解析
  2. Bean的实例化
  3. 属性填充(依赖注入)
  4. 执行BeanPostProcessor接口
  5. Bean的初始化
  6. Spring Bean的生命周期完整

AOP

实现原理

JDK动态代理、CGLIB动态代理

AOP和AspectJ

  • 实现机制:
    • Spring AOP:基于动态代理和字节码增强(在运行时通过代理对象或修改字节码来织入切面逻辑),只能在运行时织如切面逻辑,对类的侵入性相对较小。
    • AspectJ:是一个完整的AOP框架,提供了丰富的AOP语言支持。它可以通过编译时织入(Compile - time Weaving)、类加载时织入(Load - time Weaving)等方式将切面逻辑织入到目标代码中,功能更强大,能实现更细粒度的切面控制,但对项目的构建过程有一定影响,需要特定的编译器或织入器支持。
  • 功能范围:
    • Spring AOP:主要关注与Spring应用相关的切面需求,如对Spring Bean的方法进行切面增强,支持的连接点主要是方法调用。
    • AspectJ:提供了更广泛的连接点支持,除了方法调用,还包括字段访问、构造函数调用等,能满足更复杂的AOP需求。
  • 使用难度:
    • Spring AOP:与Spring框架紧密集成,使用Spring的配置或注解(如@Aspect、@Before等)就可以很方便地实现切面功能,对于熟悉Spring的开发者来说容易上手。
    • AspectJ: 由于其功能丰富和实现方式的多样性,学习曲线相对较陡,需要开发者对 AOP 概念和 AspectJ 语法有更深入的理解。

术语

  • 切面
  • 连接点
  • 切入点
  • 通知(前置通知、后置通知、返回通知、异常通知、环绕通知)
  • 目标对象
  • 代理
  • 织入

事务

4种事务特性:原子性、一致性、隔离性、持久性

5种隔离机制:默认隔离级别、读未提交、读已提交、可重复读、可串行化

7种传播行为:required、supports、mandatory、requires_new、not_supported、never、nested

事务失效场景:

  • 方法不是public修饰
  • 自调用(内部方法调用)
  • 未被Spring容器管理
  • 异步被捕获且未重新抛出
  • 异步类型不匹配
  • 数据源未配置事务管理器
  • 多线程调用

注解

  • 核心模式与组件定义:
    • @Component:标记一个类为Spring组件。
    • @Controller:标记一个类为 Spring MVC 控制器组件(是 @Component 的特化)。
    • @Service:标记一个类为服务层业务逻辑组件(是 @Component 的特化)。
    • @Repository:标记一个类为数据访问层(DAO) 组件(是 @Component 的特化),自带平台特定的异常转换功能。
    • @Configuration + @Bean:用于基于Java的配置。@Configuration 标记一个类为配置类,其内部使用 @Bean 标注的方法会定义一个Bean,并交由Spring容器管理。
  • 依赖注入与装配:
    • @Autowired:用于根据类型(byType)进行自动注入。
    • @Qualifier:与 @Autowired 配合使用,当存在多个相同类型的Bean时,通过名称(byName)来指定要注入的具体Bean。
    • @Primary:设置一个Bean为首选项。当有多个相同类型的Bean且没有指定 @Qualifier 时,优先注入带有此注解的Bean。
    • @Value:用于注入基本数据类型、SpEL表达式或配置文件中的属性值(如 @Value(“${server.port}”))。
  • Web MVC相关:
    • RequestMapping、@GetMapping、@PostMapping:将HTTP请求映射到特定的控制器方法。
    • @RequestBody:将HTTP请求的Body内容(通常是JSON/XML)绑定到方法的参数上。
    • @ResponseBody:将方法的返回值直接绑定到HTTP响应体上(通常转换为JSON/XML)。
    • @PathVariable:将URL模板变量绑定到方法参数上(如/users/{id})。
    • @RequestParam:将请求参数(URL查询参数或表单数据)绑定到方法参数上。
    • @ModelAttribute:将请求参数绑定到模型对象上,或用于在方法上提前准备模型数据。
    • @RequestHeader:将请求头(Header)的值绑定到方法参数上。
    • @CookieValue:将Cookie的值绑定到方法参数上。
    • @SessionAttribute:访问预先存在于会话(Session)中的属性。
    • @ExceptionHandler:在控制器内部声明一个方法来处理特定类型的异常。
    • @ResponseStatus:标记方法或异常类,指定HTTP响应的状态码。
  • 数据验证:
    • @Validated:Spring提供的注解,用于触发校验,支持分组校验。
    • @Valid:Java标准校验注解,通常用于方法参数上触发校验。在Spring中,两者常可互换,但@Validated功能更强大。
  • Bean生命周期与作用域:
    • @PostConstruct:标注一个方法,在Bean初始化完成后立即执行(类似于init-method)。
    • @PreDestory:标注一个方法,在Bean被容器销毁之前执行(类似于destroy-method)。
    • @Scope:定义Bean的作用域(如:singleton、prototype、requeest、session等)。
    • @Lazy:表示一个Bean是延迟初始化的,只有在第一次被使用时才会创建。
  • 配置与条件化:
    • @Profile:指定一个Bean或配置类只在特定的环境Profile激活时才会被注册(如:“dev”、“prod”)。
    • @Conditional:根据满足某个特定条件(自定义或Spring内置条件,如 @ConditionalOnProperty)才注册Bean,是更通用的条件化注解。
    • @PropertySource:指定Spring加载指定的属性文件(.properties 或 .yml)到环境(Environment)中。
  • 高级功能:
    • @Transactional:声明式事务管理。
    • @Cached、@CacheEvict、@CachePut:声明式缓存,用于方法结果的缓存和清除。
    • @Scheduled:用于声明一个方法是定时任务,可以基于 cron、固定速率或固定延迟执行。
    • @Async:声明一个方法是异步执行的,调用此方法会立即返回,实际执行将提交给TaskExecutor。
    • @EventListener:声明一个方法为应用事件监听器,用于监听Spring容器内发布的Application。

Async

内部失效原因:Spring的AOP是基于代理实现的,而内部调用会绕过代理机制。

如何避免内部调用失效?

  1. 自我注入
  2. 使用ApplicationContext获取代理对象
  3. 使用AopContext获取代理对象
  4. 拆分为单独的服务类
  5. 手动使用TaskExecutor

什么时候会失效?

  • 未使用@EnableAsync注解
  • 内部方法调用
  • 方法非public
  • 方法返回值错误
  • 方法用static修饰了
  • 方法用final修饰
  • 业务类没加@Service注解
  • 自己new的对象
  • Spring无法扫描异步类

拦截器和过滤器

过滤器和拦截器都是基于AOP思想实现的,用来解决项目中某一类问题的两种工具。

拦截器

拦截器用于请求处理之前或之后执行的某些逻辑。拦截器可以用来实现日志记录、权限检查、性能监控等功能。

过滤器

比较

  • 出身不同:过滤器来自Servlet,而拦截器来自于Spring框架。
  • 触发时机不同:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器(Controller)。过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法。
  • 实现不同:过滤器是基于方法回调实现的;拦截器是基于动态代理实现的。
  • 支持的项目类型不同:过滤器要依赖 Servlet 容器,它只能用在 Web 项目中;而拦截器是 Spring 中的一个组件,因此拦截器既可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中。
  • 使用的场景不同:拦截器主要用来实现项目中的业务判断的,过滤器通常是用来实现通用功能过滤的。

JPA和Hibernate

JPA是一套ORM的规范,定义了标准接口和注解
Hibernate是JPA规范的一种实现
Spring Data JPA 则是基于 JPA 规范的进一步抽象和封装

参考