一、IOC 与 DI
- IOC(控制反转):简单说就是把对象的创建、管理权力从代码转移到 Spring 容器。原来我们需要自己
new对象,现在由容器统一创建、装配对象,我们直接从容器中获取即可,这就是 “控制反转”。 - DI(依赖注入):容器在创建对象时,会自动把该对象依赖的其他对象注入进来。比如 Service 依赖 Dao,容器会在创建 Service 时,把 Dao 对象注入到 Service 中,不用我们手动设置。
- 声明 Bean 与依赖注入的方式:
- 声明 Bean:在类上加注解即可让容器管理,比如
@Controller(控制层)、@Service(服务层)、@Repository(数据层,现在 MyBatis 常用@Mapper)、@Component(通用组件)、@Configuration(配置类)。 - 依赖注入:常用
@Autowired(默认按类型注入)和@Resource(默认按名称注入)。比如在 Service 中注入 Dao,加@Autowired即可。
二、Bean 的线程安全与作用域
- Bean 的线程安全:Spring 的 Bean 默认是单例(整个容器中只有一个实例)。多线程并发访问时,如果 Bean 有共享的成员变量,可能存在线程安全问题(Spring 没对单例 Bean 做多线程封装)。但实际开发中,Controller、Service、Dao 通常没有可变状态(成员变量不被修改),所以大多时候是安全的。如果有线程安全问题,可自己通过代码保证(如加锁),或把 Bean 的作用域设为
prototype(每次获取都是新实例)。 - Bean 的作用域:通过
@Scope注解设置,常见取值:
singleton:默认,单例,容器中只有一个实例。prototype:多例,每次获取都是新实例。request:同一个请求内用同一个实例。session:同一个会话内用同一个实例。
三、Bean 的生命周期
Bean 的生命周期大致分为以下步骤:
- 实例化:调用构造函数创建 Bean 对象。
- 依赖注入:通过 set 方法等注入依赖(如
@Autowired注解的属性在此步赋值)。 - 处理 Aware 接口:如果 Bean 实现了
BeanNameAware、BeanFactoryAware等接口,会调用对应的方法(如获取 Bean 名称、容器对象)。 - BeanPostProcessor 前置处理:执行
BeanPostProcessor的postProcessBeforeInitialization方法,对 Bean 做前置增强。 - 初始化:执行初始化方法,比如实现
InitializingBean的afterPropertiesSet方法、加@PostConstruct注解的方法。 - BeanPostProcessor 后置处理:执行
BeanPostProcessor的postProcessAfterInitialization方法,可能在此步生成代理对象(如 AOP 增强)。 - 使用:Bean 创建完成,供业务逻辑调用。
- 销毁:容器关闭时,执行销毁方法,比如实现
DisposableBean的方法、加@PreDestroy注解的方法。
四、循环依赖
- 什么是循环依赖:两个或多个 Bean 互相依赖形成闭环,比如 A 依赖 B,B 依赖 A。
- Spring 如何解决:通过三级缓存解决大部分循环依赖:
- 一级缓存(
singletonObjects):存完全初始化的 Bean。 - 二级缓存(
earlySingletonObjects):存未完全初始化的 “半成品” Bean。 - 三级缓存(
singletonFactories):存ObjectFactory(用于创建 Bean 的工厂,可能生成代理对象)。
- 流程示例:创建 A 时,先把 A 的工厂存入三级缓存;A 需要 B,于是创建 B;B 需要 A 时,从三级缓存取 A 的工厂生成半成品 A,存入二级缓存,B 注入 A 后完成初始化并进入一级缓存;最后 A 注入 B,完成初始化进入一级缓存。
- 特殊情况:构造函数循环依赖无法通过三级缓存解决,需在构造函数参数上加
@Lazy(延迟加载)。
五、AOP
- 什么是 AOP:面向切面编程,把日志、权限、事务等与业务无关的公共逻辑抽成 “切面”,统一增强业务方法,降低耦合。
- 项目中的应用:比如记录操作日志,通过自定义注解(如
@Log)标记需要记录日志的方法,再定义切面类,用环绕通知(@Around)拦截这些方法,获取请求参数、操作人等信息并存入数据库。 - 底层实现:基于动态代理:
- JDK 动态代理:只能代理实现接口的类,生成的代理类与被代理类是 “兄弟”(同实现一个接口)。
- Cglib 动态代理:可代理未实现接口的类(不能代理 final 类),生成的代理类是被代理类的 “子类”,通过继承实现增强。
六、事务
- 事务的实现:Spring 事务底层基于 AOP,在方法执行前开启事务,执行后根据是否异常提交或回滚,通过
@Transactional注解控制。 - 事务失效的场景:
- 方法内
try-catch异常但未抛出(Spring 无法感知异常)。 - 方法抛出检查异常(默认只回滚
RuntimeException,需通过rollbackFor=Exception.class指定)。 - 方法不是
public修饰(Spring 只对 public 方法增强事务)。
- 事务传播行为:控制两个事务方法互相调用时的事务关系,常用:
REQUIRED(默认):如果有事务就加入,没有就新建。REQUIRES_NEW:无论是否有事务,都新建一个独立事务。
七、常用注解
按功能分类:
- 声明 Bean:
@Component、@Service、@Controller、@Repository、@Configuration。 - 依赖注入:
@Autowired(按类型)、@Resource(按名称)、@Qualifier(指定名称)。 - 作用域:
@Scope。 - AOP:
@Aspect(切面)、@Pointcut(切入点)、@Before/@After/@Around(通知)。 - 事务:
@Transactional。 - 初始化 / 销毁:
@PostConstruct(初始化)、@PreDestroy(销毁)。