spring循环依赖解决问题分息&spring aop核心概念解析&动态代理
课程目标:
1.明白什么是循环依赖?
2.明白Spring中的循环依赖是如何解决的?
3.明白Spring中的循环依赖是如何解决的?
4.Spring aop核心概念详解(通知、切面、切入点等等)
5.要明白aop到底是什么回事?
6.要明白aop的底层原理是如何结合动态代理去实现的
7.掌握动态代理的两种方式的写法
三级缓存获取对象的顺序
- 先从一级缓存中查找
- 再从二级缓存中查找
- 最后没有则从三级缓存中获取(ObjectFactory获取对象,有可能获取的是代理对象)
将获取到的对象,【放入二级缓存】,同时删除此beanName对应的三级缓存
三级缓存添加到对象的顺序
先将第一步new出来的对象,【添加到三级缓存】中的ObjectFactory进行保存
思考:如果一个目标对象被aop动态动态加上事务增强功能,那么Spring容器中存储的是目标对象还是增强之后的对象,还是都存储?
答案:spring只会存储一个对象,那就是aop增强之后的代理对象。
思考:aop针对目标对象产生代理对象,是发生在bean创建的哪个流程?
答案:是发生在bean初始化的过程中,具体发生在bean初始化之后,去进行aop过程
ClassA {
ClassB
}
ClassB {
ClassA
}
创建ClassA的流程
1.ClassA实例化
2.ClassB属性填充–ClassA类型变量赋值(getBean–去IOC容器中查找)
2.1. ClassB实例化
2.2 ClassB 属性填充 — ClassA类型变量赋值(getBean–去IOC容器中查找)
如果此时还找不到ClassA,那么又会从第一步开始了,这样容器就死循环了
为了不让死循环,那么我们需要此时ClassA的实例被找到
SingletonObjects集合中不存放半成品,和最终的对象是一个,我们需要在获取这个提前暴露的对象的时候,也需要判断是否进行提前代理
那么这个时候,我们就需要一个第三集缓存。(beanName,获取一个ObjectFactory的工厂类,该类就可以添加产生代理对象的逻辑)
如果是单例bean,并且允许引用、该beanname存储到singletonsCurrentlyInCreation(Set集合),那么ClassA就会被提前暴露给三级缓存,
3.ClassA初始化
4.ClassA实例放入SingletonObjects集合中(才是对外暴露的引用集合)
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 一级缓存(单例bean)(可以对外直接get到)
this.singletonObjects.put(beanName, singletonObject);
// 三级缓存 (提早产生bean实例的对象工厂ObjectFactory)
this.singletonFactories.remove(beanName);
// 二级缓存 (半成品)
this.earlySingletonObjects.remove(beanName);
// 已经注册的bean的名称集合
this.registeredSingletons.add(beanName);
}
}
2.spring中AOP的核心概念
AOP作用:可以针对目标对象进行无感知(不修改目标对象代码的情况下)进行功能增强
AOP是通过哪种方式去实现的无感知功能增强的呢?
** 静态织入(了解)
*** 使用字节码拼接技术,在编译期间,针对目标对象对应的class文件进行静态编码(asm)
** 动态织入(掌握)
*** 使用动态代理技术,在运行期间,针对目标对象进行动态代理
- AOP是一种思想,它的实现产品有多种:AspectJ, Spring Aop、Spring整合 AspectJ
- AOP核心概念分析
** 连接点
** 切入点
** 目标对象
** 代理对象
** 通知
*** 前置通知
*** 后置通知
*** 环绕通知
*** 最终通知
*** 异常通知
** 切面/通知器
** 引介