5.22作业

IOC的理解(what why how)?Spring如何解决循环依赖问题?

SpringIOC 通过三级缓存来解决循环依赖问题,三级缓存指的是三个Map:

singletonObjects:一级缓存,key为BeanName,value为Bean,日常获取Bean的地方
earlySingletonObjects:二级缓存,key为BeanName,value为Bean,已经实例化但还没有进行属性注入的Bean,由三级缓存放入
singletonFactories:三级缓存,key为BeanName,value为对象工厂(ObjectFactory)
在实际使用中,要获取一个bean,先从一级缓存一直查找到三级缓存,缓存bean的时候是从三级到一级的顺序保存,并且缓存bean的过程中,三个缓存都是互斥的,只会保持bean在一个缓存中,而且,最终都会在一级缓存中。

解决循环依赖
SpringIOC解决循环依赖的思路就是依靠缓存,同时还得引出个概念即早期暴露引用。我们知道在IOC容器里Bean的初始化的过程分为三个步骤:创建实例、属性注入实例、回调实例实现的接口方法。

解决思路就在这:当我们创建实例与属性注入实例这俩个步骤之间的时候,我们引入缓存,将这些已经创建好但是并没有注入属性的实例放到缓存里,而这些放在缓存里但是没有被注入属性的实例对象,就是解决循环依赖的方法。

打个比方:A对象的创建需要引用到B对象,而B对象的创建也需要A对象,而此时当B对象创建的时候直接从缓存里引用A对象(虽然不是完全体A对象,毕竟没有赋值处理),当B对象完成创建以后再被A对象引用进去,则A对象也完成了创建。

解决循环依赖具体过程
对Bean的创建最为核心三个方法解释如下:

createBeanInstance:实例化,通过反射调用对象构造方法实例化对象;
populateBean:填充属性,主要是对bean的依赖属性进行赋值;
initializeBean:初始化,可以回调InitializingBean、initMethod等方法。
实例化A的时候,先将A创建(早期对象)放入一个池子(singletonFactories)中。这个时候虽然属性没有赋值,但是容器已经能认识这个是A对象,只是属性全是null而已。在populateBean方法中对属性赋值的时候,发现A依赖了B,那么就先去创建B,又走一遍bean的创建过程(创建B)。同样也会把B的早期对象放入缓存(singletonFactories)中。当B又走到 populateBean方法(负责填充Bean实例属性的方法)的时候,发现依赖了A,我们又去创建A,但是这个时候去创建A,发现我们在缓存(singletonFactories)能找到A(早期对象),此时会通过A的ObjectFactory获取A,并把A从三级缓存移到二级缓存。然后就可以把B的A属性赋值了,这个时候B就初始化完成了,初始化完成后就会把B从三级缓存移到一级缓存。完成B实例化后,回到A调用的populateBean方法中。返回的就是B对象了,对A的B属性进行赋值就可以了。
 

AOP的理解(what why how)?

概念:
AOP (面向切面编程):即面向规则编程,找出多个类中有一定规律的代码,开发时拆开,运行时再合并。本质:解耦,专人做专事。

目的:

(1)、把核心业务和非核心业务进行分离    

(2)、把多个非核心业务处理(点)变成一个切面(之前的非核心业务代码需要写多次变成只需要写一次。)

要求:

只有当核心类中有多个业务需要进行处理的时候使用AOP较为合理,如果只有一个业务需要被处理那么就没有必要使用AOP了。

应用场景:
1、用于日志打印

2、用于全局异常处理拦截

3、返回值统一处理

4、多数据源切换

AOP代理主要分为静态代理和动态代理,动态代理是为了解决静态代理的弊端诞生的。

 静态代理的弊端: 一个代理接口只能服务于一种类型的对象

静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表,

使用AspectJ的编译时增强实现AOP AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。 AspectJ会在编译阶段将Aspect织入Java字节码中, 运行的时候就是经过增强之后的AOP对象。

spring默认使用jdk动态代理,如果没有实现接口,就使用cglib代理;

JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

流程:

1、通过实现 InvocationHandler 接口创建自己的调用处理器;

2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

4、调用处理器对象作为参数传入构造函数创建动态代理类实例。

Java动态代理的使用及原理分析
cglib代理:CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并在拦截方法相应地方织入横切逻辑。

区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值