一、Spring IOC(控制反转)深度解析
1. IOC 核心概念
-
控制反转(IoC):对象不自己管理依赖,而由容器负责注入。
-
依赖注入(DI):IoC 的具体实现方式,主要三种:
-
构造器注入:通过构造方法注入
-
Setter 注入:通过 setter 方法注入
-
注解注入:
@Autowired、@Resource
-
优点:
-
解耦:业务对象不依赖具体实现
-
易测试:可以注入 Mock 对象
-
易扩展:通过 BeanPostProcessor 自定义逻辑
2. IOC 容器架构
Spring 容器分为两类:
| 容器 | 特点 |
|---|---|
BeanFactory | 最基础 IOC 容器,延迟加载 Bean |
ApplicationContext | BeanFactory 子类,提供事件、国际化支持、AOP |
核心实现类:
-
DefaultListableBeanFactory:管理 Bean 定义和实例化 -
AnnotationConfigApplicationContext:注解方式配置容器 -
ClassPathXmlApplicationContext:XML 配置方式容器
3. Bean 的定义与注册
-
BeanDefinition:Bean 的元数据(类名、作用域、构造器、依赖)
-
注册流程:
-
容器扫描包或读取 XML
-
将每个 Bean 的信息封装成
BeanDefinition -
存入
DefaultListableBeanFactory.beanDefinitionMap
-
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(MyService.class);
beanFactory.registerBeanDefinition("myService", bd);
4. Bean 的实例化与依赖注入流程
4.1 Bean 创建总流程
-
检查单例缓存
-
创建 Bean 实例(反射或工厂方法)
-
填充属性(依赖注入)
-
执行
Aware接口回调 -
执行
BeanPostProcessor.postProcessBeforeInitialization -
调用
InitializingBean.afterPropertiesSet()或自定义 init 方法 -
执行
BeanPostProcessor.postProcessAfterInitialization -
添加到单例缓存
4.2 核心源码流程
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 实例化 Bean
Object bean = instantiateBean(beanName, mbd, args);
// 2. 属性填充
populateBean(beanName, mbd, bean);
// 3. 初始化前置处理
bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 4. 初始化
invokeInitMethods(beanName, bean, mbd);
// 5. 初始化后置处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return bean;
}
4.3 循环依赖解决
-
单例 Bean 三缓存机制:
-
singletonObjects:一级缓存,真正创建完成的 Bean -
earlySingletonObjects:二级缓存,提前暴露对象引用 -
singletonFactories:三级缓存,存放 ObjectFactory 生成代理
-
-
原理:提前暴露 Bean 引用,解决 A 依赖 B,B 又依赖 A 的问题
5. 注解依赖注入源码解析
-
@Autowired通过AutowiredAnnotationBeanPostProcessor处理 -
解析 Bean 的字段、方法
-
调用
BeanFactory.getBean获取依赖 -
注入字段或方法
Field field = MyService.class.getDeclaredField("userRepository");
field.setAccessible(true);
field.set(myService, beanFactory.getBean(UserRepository.class));
二、Spring AOP(面向切面编程)深度解析
1. 核心概念
| 名称 | 含义 |
|---|---|
| 切面(Aspect) | 横切逻辑,例如日志、事务 |
| 通知(Advice) | 具体增强逻辑,如前置、后置、环绕 |
| 切点(Pointcut) | 指定在哪些方法上应用增强 |
| 目标对象(Target) | 被代理对象 |
| 代理对象(Proxy) | 代理后的对象,实际调用增强逻辑 |
2. Spring AOP 实现方式
-
JDK 动态代理
-
条件:目标类实现接口
-
原理:
Proxy.newProxyInstance生成代理对象 -
优势:简单,无需第三方库
-
-
CGLIB 动态代理
-
条件:目标类无接口或强制使用
-
原理:生成子类,重写方法织入增强逻辑
-
优势:支持类代理
-
3. 核心组件与源码
| 组件 | 作用 |
|---|---|
ProxyFactory | 代理对象工厂 |
AdvisedSupport | 保存目标对象、切点、通知 |
MethodInterceptor | 通知实现 |
AopProxy | 生成代理对象(JDK/CGLIB) |
AnnotationAwareAspectJAutoProxyCreator | BeanPostProcessor,自动生成代理 |
4. AOP 生成代理的流程
-
容器初始化,扫描切面类和注解
-
解析
@Aspect、@Before、@Around -
封装
Advisor→MethodInterceptor -
Bean 初始化时:
-
AnnotationAwareAspectJAutoProxyCreator调用wrapIfNecessary -
判断 Bean 是否需要增强
-
创建 JDK/CGLIB 代理对象替换原 Bean
-
-
调用代理对象方法时:
-
触发
MethodInterceptor.invoke() -
执行前置、环绕、后置通知
-
最终调用目标方法
-
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
before(); // 前置通知
Object ret = invocation.proceed(); // 调用目标方法
after(); // 后置通知
return ret;
}
5. AOP 与 IOC 的关系
-
AOP 依赖 IOC 容器管理切面 Bean
-
Bean 初始化阶段,通过
BeanPostProcessor生成代理 -
源码类:
AnnotationAwareAspectJAutoProxyCreator→wrapIfNecessary
6. 代理对象内部结构
-
JDK 动态代理
-
Proxy→InvocationHandler.invoke()→ 通知链 → 目标方法
-
-
CGLIB 动态代理
-
生成子类 → 拦截方法调用 → 执行通知链 → 调用父类方法
-
7. 常见问题与优化
-
内部调用不生效
-
原因:自调用不经过代理
-
解决:通过注入代理 Bean 或使用
AopContext.currentProxy()
-
-
非 public 方法不被 JDK 代理
-
解决:使用 CGLIB 或 public 方法
-
-
循环依赖与代理
-
代理生成在 Bean 初始化后阶段,注意顺序
-
-
性能优化
-
代理只在需要增强时生成
-
多个通知按链表顺序执行
-
8. 总结
| 特性 | IOC | AOP |
|---|---|---|
| 核心 | 对象管理、解耦 | 横切关注点增强 |
| 实现 | BeanFactory、ApplicationContext | JDK/CGLIB 动态代理 |
| 扩展点 | BeanPostProcessor、FactoryBean | MethodInterceptor、Advisor |
| 核心类 | DefaultListableBeanFactory | ProxyFactory、AnnotationAwareAspectJAutoProxyCreator |
| 注意点 | 循环依赖、初始化顺序 | 内部调用不生效、接口 vs 类代理 |
1277

被折叠的 条评论
为什么被折叠?



