从反射到动态代理到aop到spring为什么需要三级缓存

概要

spring 主要有两大思想,一个是 IOC,一个就是 AOP。对于 IOC 容器中bean 的创建就是使用了 Java 的反射技术;而对于 spring 的核心 AOP 来说,我们知道 AOP 的实现原理之一就是 JDK 的动态代理机制,而 JDK 的动态代理本质就是利用了反射技术来实现的

反射

官方的解释:
java程序在运行状态中,对于任意一个类,都能够在运行时知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

反射赋予jvm动态编译的能力,我们在程序运行中,可以获得到我们任何想要的类,方法,属性,那么就为我们动态代理的实现提供了基础,因为我们可以在运行中,通过反射,可以创建任意一个类的代理对象

动态代理

利用反射机制在运行时创建代理对象,然后通过代理对象来调用真实对象的方法,可以根据传入不同的类,生成不同的代理对象去执行真实对象的方法

aop

面向切面编程,将业务代码和非业务代码分离,如日志输入,权限控制等进行分离,利用动态代理的方式实现,代理我们的方法执行,我们可以在方法执行前,后对参数和结果进行修改,也可以根据抛出的异常做对应得日志输出,项目中用得aop做得全局异常处理

个人认为是拦截器+动态代理的结合,拦截器拦截到需要aop的对象,在动态代理执行之前可以做一些操作,然后在动态代理方法执行结束之后,也可以在做一些操作。

  • @Pointcut包含两个过滤器:类过滤器,方法过滤器,两者共同作用就可以判断添加增强器的位置。
  • Advice通知是一个增强器,是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。

三级缓存解决循环依赖

spring利用两级缓存可以解决bean的循环依赖,利用三级缓存解决aop的循环依赖

循环依赖

A依赖B(对象A中有一个属性Class B),B依赖A(对象B中有一个属性Class A)
当我们创建beanA发现没有BeanB,那我们就去创建BeanB,创建BeanB发现没有BeanA
,就去创建BeanA,如此,便开始循环创建

如何解决

三级缓存,三个Map

  1. 一级缓存:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
  2. 二级缓存:提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
  3. 三级缓存:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖,可以根据原始bean还是代理bean,生成对应的原始bean对象还是代理bean对象

步骤:
首先,我们开始创建A对象,在三级缓存添加对应的工厂BeanA,然后在依赖注入的时候,发现没有B,然后在三级缓存中添加对应的工厂beanB,然后依赖注入时,通过工厂beanA生产A对象(如果有代理,返回的是代理对象),此时,会将生产的A对象放到二级缓存,三级缓存的工厂beanA会被删除,然后注入到B中,B就可以完成实例化,初始化,然后将B放到了一级缓存中,然后在A在进行依赖注入,初始化的操作,即可完成

为什么只能用三级缓存,不能使用二级缓存

如果没有三级缓存,那么创建过程是这样的:A创建,然后属性注入,发现B没有创建,然后创建B,B可以完成实例化和初始化,初始化之后调用AOP的后置处理器,拿到B的代理对象,然后在对A进行属性注入,A初始化之后,也会调用AOP的后置处理器类,拿到A的代理对象,此时会发现,A中的B是B的代理对象,B中的A不是A的代理对象,而是原始对象
解决方案:引入三级缓存,三级缓存有bean工厂,可以根据原始bean还是代理bean,生成对应的原始bean对象还是代理bean对象,在实例化的时候如果使用了aop,那么拿到的就是代理对象,就会解决上面的问题

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值