Qouson's blog Qouson's blog
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

qouson

Java界的小学生
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Spring

    • Spring
      • Bean生命周期
        • 简单版
      • 循环依赖
        • 循环依赖的场景
        • 循环依赖的情况
        • 三级缓存
        • 循环依赖的解决
        • 只用两级缓存能解决循环依赖吗?
      • AOP
        • 静态代理
        • 动态代理
        • 动态代理模式
        • JDK动态代理
        • CGLIB动态代理
      • 事务
        • 事务类型
        • 事务原理
        • 事务隔离级别
        • 事务传播行为
      • Spring常用注解
    • AOP

    • IOC

  • SpringMVC

  • SpringBoot

  • SpringCloud

  • Spring
  • Spring
qouson
2024-06-01
目录

Spring

# Sring

# Bean生命周期

# 简单版

  • 实例化,调用类的无参构造方法,生成普通对象
  • 依赖注入(反射给加了@Autowired和@Resource的属性赋值)
  • 初始化前
    • 检查Aware的相关接口并设置相关依赖
    • 调用BeanPostProcessor的postProcessorBeforeInitialization()
    • 是否实现InitializingBean接口,调用afterPropertiesSet()方法
    • 是否配置自定义的init-method方法
  • 初始化
  • 初始化后
    • 调用BeanPostProcessor的postProcessAfterInitialization()
    • AOP就是在这个阶段
  • 使用中
  • 销毁
    • 是否实现DisposableBean接口,调用destroy()方法
    • 是否配置自定义的destroy-method方法

# 循环依赖

# 循环依赖的场景

A创建的过程需要B,于是A将自己放到三级缓存,去实例化B,B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再去三级缓存找A,找到了,把A挪到二级缓存,然后B实例化完成

# 循环依赖的情况

  • 属性循环依赖
  • 构造器循环依赖----这种情况Spring无法解决循环依赖

# 三级缓存

  • 三级缓存
    • 一级缓存:SingletonObjects,存放已经实例化好并初始化好的完整对象
    • 二级缓存:EarlySingletonObjects,存放需要提前暴露的已经实例化但未初始化好的早期对象
    • 三级缓存:SingletonFactories,存放对象工厂(lambda表达式,打破循环依赖的关键,解决AOP依赖原始对象的问题)
  • 其实还有一个缓存,就是earlyProxyReferences,它用来记录某个原始对象是否进行过AOP增强,如果进行了增强,那么在循环依赖的时候,需要把earlyProxyReferences中的对象也拿出来放到二级缓存中

# 循环依赖的解决

当A、B两个类发生循环依赖时:

A实例的初始化过程:

  1. 创建 A 实例,实例化的时候把 A 的对象工厂放入三级缓存,表示 A 开始实例化了,虽然这个对象还不完整,但是先曝光出来让大家知道。
  2. A 注入属性时,发现依赖 B,此时 B 还没有实例化,所以去实例化 B
  3. 同样,B 注入属性时发现依赖 A,就从缓存中找 A 对象。依次从一级到三级缓存查询 A。 发现可以从三级缓存中通过对象工厂拿到 A,虽然 A 还不太完善,但是存在,就把 A 放入到二级缓存,同时删除三级缓存中的 A,此时 B 已经实例化并且初始化完成了,把 B 放入到一级缓存。
  4. 接着 A 继续属性赋值,顺利从一级缓存拿到实例化且初始化好的 B 对象,A 对象初始化完成,删除二级缓存中 A ,同时把 A 放入到一级缓存。
  5. 最后,一级缓存中保存着实例化和初始化好的 A 、B对象。

# 只用两级缓存能解决循环依赖吗?

  • 通常情况可,但是如果涉及AOP,还是需要三级缓存
  • 假设只有二级缓存,在二级缓存中放的一个普通Bean对象,Bean初始化过程中,通过BeanPostProcessor去生成代理对象之后,覆盖掉二级缓存中的普通Bean对象,就会导致Bean对象不一致了

# AOP

# 静态代理

  • 静态代理模式:自己手动编写代理类,代理类和被代理类实现相同的接口
  • 优点:可以做到在代理类中增强被代理类的功能
  • 缺点:需要为每一个被代理类都编写一个代理类,工作量比较大

# 动态代理

# 动态代理模式

JDK动态代理和CGLIB动态代理

# JDK动态代理

需要被代理类实现接口,否则无法使用JDK动态代理,反射生成一个代理接口的匿名类

# CGLIB动态代理

asm字节码编辑技术,基于classload装载

# 事务

# 事务类型

  • 编程式事务
  • 声明式事务

# 事务原理

  • 前提是关闭自动提交
  • 采用不同的连接器
  • 用AOP新建立链接
  • ThreadLocal管理当前事务

# 事务隔离级别

  • 读未提交Read Uncommitted
  • 读已提交Read Committed
  • 不可重复读Repeatable Read
  • 串行化Serializable

# 事务传播行为

# Spring常用注解

编辑 (opens new window)
上次更新: 2024/06/01, 23:33:02
Spring-AOP

Spring-AOP→

最近更新
01
杂乱无章
12-25
02
基础-大彬
11-14
03
集合-大彬
11-14
更多文章>
Theme by Vdoing | Copyright © 2023-2025 qouson
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式