Spring IOC和AOP详解(二)

一、Spring IOC(控制反转)深度解析

1. IOC 核心概念

  • 控制反转(IoC):对象不自己管理依赖,而由容器负责注入。

  • 依赖注入(DI):IoC 的具体实现方式,主要三种:

    1. 构造器注入:通过构造方法注入

    2. Setter 注入:通过 setter 方法注入

    3. 注解注入:@Autowired@Resource

优点

  • 解耦:业务对象不依赖具体实现

  • 易测试:可以注入 Mock 对象

  • 易扩展:通过 BeanPostProcessor 自定义逻辑


2. IOC 容器架构

Spring 容器分为两类:

容器特点
BeanFactory最基础 IOC 容器,延迟加载 Bean
ApplicationContextBeanFactory 子类,提供事件、国际化支持、AOP

核心实现类:

  • DefaultListableBeanFactory:管理 Bean 定义和实例化

  • AnnotationConfigApplicationContext:注解方式配置容器

  • ClassPathXmlApplicationContext:XML 配置方式容器


3. Bean 的定义与注册

  • BeanDefinition:Bean 的元数据(类名、作用域、构造器、依赖)

  • 注册流程

    1. 容器扫描包或读取 XML

    2. 将每个 Bean 的信息封装成 BeanDefinition

    3. 存入 DefaultListableBeanFactory.beanDefinitionMap

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(MyService.class);
beanFactory.registerBeanDefinition("myService", bd);

4. Bean 的实例化与依赖注入流程

4.1 Bean 创建总流程

  1. 检查单例缓存

  2. 创建 Bean 实例(反射或工厂方法)

  3. 填充属性(依赖注入)

  4. 执行 Aware 接口回调

  5. 执行 BeanPostProcessor.postProcessBeforeInitialization

  6. 调用 InitializingBean.afterPropertiesSet() 或自定义 init 方法

  7. 执行 BeanPostProcessor.postProcessAfterInitialization

  8. 添加到单例缓存

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 三缓存机制:

    1. singletonObjects:一级缓存,真正创建完成的 Bean

    2. earlySingletonObjects:二级缓存,提前暴露对象引用

    3. singletonFactories:三级缓存,存放 ObjectFactory 生成代理

  • 原理:提前暴露 Bean 引用,解决 A 依赖 B,B 又依赖 A 的问题


5. 注解依赖注入源码解析

  1. @Autowired 通过 AutowiredAnnotationBeanPostProcessor 处理

  2. 解析 Bean 的字段、方法

  3. 调用 BeanFactory.getBean 获取依赖

  4. 注入字段或方法

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 实现方式

  1. JDK 动态代理

    • 条件:目标类实现接口

    • 原理:Proxy.newProxyInstance 生成代理对象

    • 优势:简单,无需第三方库

  2. CGLIB 动态代理

    • 条件:目标类无接口或强制使用

    • 原理:生成子类,重写方法织入增强逻辑

    • 优势:支持类代理


3. 核心组件与源码

组件作用
ProxyFactory代理对象工厂
AdvisedSupport保存目标对象、切点、通知
MethodInterceptor通知实现
AopProxy生成代理对象(JDK/CGLIB)
AnnotationAwareAspectJAutoProxyCreatorBeanPostProcessor,自动生成代理

4. AOP 生成代理的流程

  1. 容器初始化,扫描切面类和注解

  2. 解析 @Aspect@Before@Around

  3. 封装 AdvisorMethodInterceptor

  4. Bean 初始化时:

    • AnnotationAwareAspectJAutoProxyCreator 调用 wrapIfNecessary

    • 判断 Bean 是否需要增强

    • 创建 JDK/CGLIB 代理对象替换原 Bean

  5. 调用代理对象方法时:

    • 触发 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 生成代理

  • 源码类:AnnotationAwareAspectJAutoProxyCreatorwrapIfNecessary


6. 代理对象内部结构

  • JDK 动态代理

    • ProxyInvocationHandler.invoke() → 通知链 → 目标方法

  • CGLIB 动态代理

    • 生成子类 → 拦截方法调用 → 执行通知链 → 调用父类方法


7. 常见问题与优化

  1. 内部调用不生效

    • 原因:自调用不经过代理

    • 解决:通过注入代理 Bean 或使用 AopContext.currentProxy()

  2. 非 public 方法不被 JDK 代理

    • 解决:使用 CGLIB 或 public 方法

  3. 循环依赖与代理

    • 代理生成在 Bean 初始化后阶段,注意顺序

  4. 性能优化

    • 代理只在需要增强时生成

    • 多个通知按链表顺序执行


8. 总结

特性IOCAOP
核心对象管理、解耦横切关注点增强
实现BeanFactory、ApplicationContextJDK/CGLIB 动态代理
扩展点BeanPostProcessor、FactoryBeanMethodInterceptor、Advisor
核心类DefaultListableBeanFactoryProxyFactory、AnnotationAwareAspectJAutoProxyCreator
注意点循环依赖、初始化顺序内部调用不生效、接口 vs 类代理
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值