循环依赖指两个或多个 Bean 之间相互依赖形成闭环的情况。例如,Bean A 依赖 Bean B,而 Bean B 同时依赖 Bean A,这种相互引用的关系即为循环依赖。
Spring 通过三级缓存机制解决单例 Bean 的循环依赖:
一级缓存(singletonObjects):存储完全初始化完成的 Bean。
二级缓存(earlySingletonObjects):存储提前暴露的、未完全初始化的 Bean 实例。
三级缓存(singletonFactories):存储 Bean 的工厂对象,用于在需要时创建提前暴露的实例。
流程:当创建 Bean A 时,先将其工厂放入三级缓存,若此时依赖 Bean B,创建 Bean B 时发现依赖 A,便从三级缓存获取 A 的提前暴露实例,放入二级缓存,完成 B 的初始化后,A 可继续依赖 B 完成初始化,最终存入一级缓存。
不够。三级缓存的核心作用是处理 Bean 的动态代理场景:若 Bean 需要被代理,三级缓存中的工厂会生成代理对象而非原始对象。若仅用二级缓存,无法延迟生成代理对象(需在初始化前确定是否代理),可能导致循环依赖时注入的是原始对象而非代理对象,破坏代理逻辑。三级缓存通过工厂延迟创建代理对象,确保注入的是正确的代理实例。
Spring 核心模块包括:
Spring Core:核心容器,实现 IOC 容器功能,包括 BeanFactory、ApplicationContext 等。
Spring AOP:面向切面编程,提供动态代理、通知、切点等功能。
Spring Context:基于 Core 模块,扩展了国际化、事件传播、资源加载等功能。
Spring DAO/ORM:数据访问模块,整合 JDBC、MyBatis、Hibernate 等持久层框架。
Spring Web:Web 应用支持,包括 Spring MVC、WebSocket 等。
Spring Test:测试支持,整合 JUnit 等测试框架。
IOC(Inversion of Control,控制反转)是 Spring 的核心思想,指将对象的创建、依赖管理等控制权从业务代码转移到 Spring 容器,由容器统一管理对象的生命周期和依赖关系,而非手动通过new创建对象。
降低代码耦合度:对象依赖由容器管理,减少硬编码依赖。
提高代码复用性:容器可复用对象实例(如单例 Bean)。
便于测试:依赖注入使 Mock 对象替换更简单。
集中管理:对象的创建、初始化、销毁等统一由容器控制,便于配置和维护。
DI(Dependency Injection,依赖注入)是 IOC 的具体实现方式,指容器在创建对象时,自动将其依赖的其他对象注入到该对象中,无需手动调用setter或构造方法设置依赖。常见方式有构造器注入、setter 注入、字段注入。
Spring Bean 是由 Spring IOC 容器管理的对象,是应用程序的组件。Bean 的创建、初始化、依赖注入、销毁等过程均由容器控制,开发者通过配置(XML、注解)定义 Bean 的类型、依赖关系和生命周期。
BeanFactory 是 Spring IOC 容器的顶层接口,提供了获取 Bean、判断 Bean 是否存在等基础功能,是 Spring 容器的核心。它采用懒加载模式(获取 Bean 时才创建),适合资源有限的场景,常见实现类有DefaultListableBeanFactory。
FactoryBean 是一个工厂 Bean 接口,用于创建复杂或特殊的 Bean。实现该接口的类可自定义 Bean 的创建逻辑,容器通过getObject()方法获取其创建的 Bean 实例。例如,MyBatis 的SqlSessionFactoryBean用于创建SqlSessionFactory。
ObjectFactory 是一个函数式接口,用于延迟获取 Bean 实例,定义了getObject()方法。它通常用于循环依赖场景,作为三级缓存的存储对象,在需要时创建 Bean 的早期实例,避免提前初始化。
ApplicationContext 是 BeanFactory 的子接口,扩展了更多功能,是更完整的 IOC 容器实现。它在容器启动时预加载所有单例 Bean,支持国际化、事件发布、资源加载等,常见实现类有ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。
共 6 种作用域:
singleton:单例,容器中仅一个实例(默认)。
prototype:原型,每次获取都创建新实例。
request:Web 环境中,每个请求对应一个实例。
session:Web 环境中,每个会话对应一个实例。
application:Web 环境中,整个应用生命周期一个实例。
websocket:Web 环境中,每个 WebSocket 会话对应一个实例。
主要有 3 种:
构造器注入:通过构造方法参数注入依赖,适合必填依赖。
setter 注入:通过setter方法注入依赖,适合可选依赖。
字段注入:直接在字段上用@Autowired注解注入,简洁但不利于测试。
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,通过将横切关注点(如日志、事务、权限)从业务逻辑中分离,实现代码解耦。核心思想是 “横向抽取”,在不修改原有代码的情况下增强功能。
Spring AOP 默认根据目标类是否实现接口选择代理方式:
若目标类实现接口,使用JDK 动态代理(基于接口生成代理类)。
若未实现接口,使用CGLIB 动态代理(基于继承生成目标类的子类)。
区别:JDK 代理只能代理接口方法,CGLIB 可代理类方法;JDK 代理效率在调用次数多时更高,CGLIB 在创建代理时开销更大。
Spring AOP 的拦截链通过MethodInterceptor接口实现,多个拦截器(通知)按顺序组成链。当目标方法被调用时,拦截器链依次执行:先执行前置通知,再执行目标方法,最后执行后置通知、异常通知或最终通知。拦截链的顺序由通知的优先级(如@Order注解)或配置顺序决定。
实现方式:Spring AOP 基于动态代理(运行时增强),AspectJ 基于字节码编织(编译期或类加载期增强)。
功能范围:AspectJ 支持更多切点表达式和通知类型,功能更全面;Spring AOP 更轻量,集成于 Spring 生态。
适用场景:Spring AOP 适合简单的横切逻辑,AspectJ 适合复杂的切面需求(如私有方法增强)。
实例化:容器通过构造方法创建 Bean 实例。
属性注入:容器将依赖的 Bean 注入到当前 Bean 的字段或 setter 方法。
初始化前:执行BeanPostProcessor的postProcessBeforeInitialization方法(前置处理)。
初始化:执行@PostConstruct注解方法、InitializingBean的afterPropertiesSet方法、自定义初始化方法。
初始化后:执行BeanPostProcessor的postProcessAfterInitialization方法(后置处理,如生成代理)。
使用:Bean 可被应用程序使用。
销毁:容器关闭时,执行@PreDestroy注解方法、DisposableBean的destroy方法、自定义销毁方法。
Spring MVC 是 Spring 框架的 Web 模块,基于 MVC(Model-View-Controller)模式,用于开发 Web 应用。它通过 DispatcherServlet(前端控制器)统一处理请求,将请求分发给对应的处理器(Controller),并通过视图解析器返回页面或数据,简化了 Web 层的开发,支持 RESTful 风格接口。
客户端发送请求至 DispatcherServlet。
DispatcherServlet 根据请求 URL 调用 HandlerMapping,获取对应的 Handler(Controller 方法)。
HandlerMapping 返回 HandlerExecutionChain(包含 Handler 和拦截器)。
DispatcherServlet 通过 HandlerAdapter 调用 Handler 处理请求。
Handler 执行完成后返回 ModelAndView(数据模型和视图名)。
DispatcherServlet 将 ModelAndView 交给 ViewResolver 解析,得到具体 View。
View 渲染模型数据,生成响应返回客户端。
Spring MVC 中存在两个容器:
父容器:由 ContextLoaderListener 初始化,管理 Service、Dao 等业务层 Bean。
子容器:由 DispatcherServlet 初始化,管理 Controller、ViewResolver 等 Web 层 Bean。
关系:子容器可访问父容器的 Bean,父容器不能访问子容器的 Bean,实现了分层隔离。
工厂模式:BeanFactory、FactoryBean 创建 Bean。
单例模式:默认的 Bean 作用域(singleton)。
代理模式:AOP 的动态代理(JDK/CGLIB)。
观察者模式:事件监听机制(ApplicationEvent、ApplicationListener)。
模板方法模式:JdbcTemplate、TransactionTemplate 等模板类。
适配器模式:HandlerAdapter 适配不同的 Handler。
基于数据库隔离级别,Spring 定义了 5 种:
DEFAULT:默认,使用数据库的隔离级别。
READ_UNCOMMITTED:读未提交,允许脏读。
READ_COMMITTED:读已提交,防止脏读,允许不可重复读和幻读。
REPEATABLE_READ:可重复读,防止脏读、不可重复读,允许幻读。
SERIALIZABLE:串行化,最高隔离级别,防止所有并发问题,但性能低。
共 7 种,定义了事务方法调用另一个事务方法时的行为:
REQUIRED:默认,若当前有事务则加入,否则新建。
SUPPORTS:若当前有事务则加入,否则以非事务执行。
MANDATORY:必须在事务中执行,否则抛异常。
REQUIRES_NEW:新建事务,若当前有事务则挂起。
NOT_SUPPORTED:以非事务执行,若当前有事务则挂起。
NEVER:必须以非事务执行,否则抛异常。
NESTED:若当前有事务,则嵌套在当前事务中执行(保存点机制)。
用于控制多个事务方法之间的交互方式,解决复杂业务场景中的事务管理问题。例如:
调用方和被调用方共用一个事务(REQUIRED)。
被调用方需要独立事务(REQUIRES_NEW),即使失败也不影响调用方事务。
禁止在事务中执行(NEVER),避免误操作。
轻量:核心包体积小,无侵入性。
松耦合:IOC 和 DI 降低组件依赖。
扩展性强:支持多种框架整合(MyBatis、Hibernate 等)。
AOP 支持:方便实现日志、事务等横切功能。
事务管理:简化数据库事务操作,支持声明式事务。
一站式:提供 Web、数据访问等全方位支持。
切面(Aspect):封装横切关注点的类(如日志切面)。
连接点(Joinpoint):程序执行过程中可被增强的点(如方法调用、字段赋值)。
切点(Pointcut):通过表达式指定的具体连接点(如所有service包下的方法)。
通知(Advice):切面的具体增强逻辑(如前置通知、后置通知)。
目标对象(Target):被增强的对象。
代理(Proxy):AOP 为目标对象创建的代理对象。
织入(Weaving):将切面应用到目标对象并创建代理的过程。
前置通知(Before):目标方法执行前执行。
后置通知(After):目标方法执行后(无论是否异常)执行。
返回通知(AfterReturning):目标方法正常返回后执行。
异常通知(AfterThrowing):目标方法抛出异常后执行。
环绕通知(Around):包裹目标方法,可自定义执行逻辑(如控制是否执行目标方法)。
资源定位:读取配置文件(XML / 注解),定位 Bean 定义信息。
BeanDefinition 载入:将配置信息解析为BeanDefinition对象(包含 Bean 的类名、属性、依赖等)。
BeanDefinition 注册:将BeanDefinition存入BeanDefinitionRegistry(如DefaultListableBeanFactory)。
初始化容器:执行refresh()方法,初始化 BeanFactory、注册 BeanPostProcessor、初始化事件机制等。
Bean 实例化:对单例 Bean(非懒加载)进行实例化、属性注入、初始化,存入一级缓存。
容器就绪:IOC 容器初始化完成,可对外提供 Bean 服务。