Spring Bean的生命周期
Spring bean 的生命周期流程图:
- 实例化 bean 对象,类似于 new XXObject();
- 将配置文件中配置的属性填充到刚刚创建的 bean 对象中;
- 检查 bean 对象是否实现了 Aware 一类的接口,如果实现了则把相应的依赖设置到 bean 对象中。比如如果 bean 实现了 BeanFactoryAware 接口,Spring 容器在实例化bean的过程中,会将 BeanFactory 容器注入到 bean 中;
- 调用 BeanPostProcessor 前置处理方法,即 postProcessBeforeInitialization(Object bean, String beanName);
- 检查 bean 对象是否实现了 InitializingBean 接口,如果实现,则调用 afterPropertiesSet 方法。或者检查配置文件中是否配置了 init-method 属性,如果配置了,则去调用 init-method 属性配置的方法;
- 调用 BeanPostProcessor 后置处理方法,即 postProcessAfterInitialization(Object bean, String beanName)。我们所熟知的 AOP 就是在这里将 Adivce 逻辑织入到 bean 中的;
- 注册 Destruction 相关回调方法;
- bean 对象处于就绪状态,可以使用了;
- 应用上下文被销毁,调用注册的 Destruction 相关方法。如果 bean 实现了 DispostbleBean 接口,Spring 容器会调用 destroy 方法。如果在配置文件中配置了 destroy 属性,Spring 容器则会调用 destroy 属性对应的方法;
在设置属性值的时候会涉及到属性依赖问题:
在这一步中,对于普通类型的属性,例如 String,Integer等,比较容易处理,直接设置即可。但是如果某个 bean 对象依赖另一个 bean 对象,此时就不能直接设置了。Spring 容器首先要先去实例化 bean 依赖的对象,实例化好后才能设置到当前 bean 中。大致流程如下:
上面图片描述的依赖比较简单,就是 BeanA 依赖 BeanB。现在考虑这样一种情况,BeanA 依赖 BeanB,BeanB 依赖 BeanC,BeanC 又依赖 BeanA。三者形成了循环依赖,如下所示:
对于这样的循环依赖,根据依赖注入方式的不同,Spring 处理方式也不同。如果依赖靠构造器方式注入,则无法处理,Spring 直接会报循环依赖异常。这个理解起来也不复杂,构造 BeanA 时需要 BeanB 作为构造器参数,此时 Spring 容器会先实例化 BeanB。构造 BeanB 时,BeanB 又需要 BeanC 作为构造器参数,Spring 容器又不得不先去构造 BeanC。最后构造 BeanC 时,BeanC 又依赖 BeanA 才能完成构造。此时,BeanA 还没构造完成,BeanA 要等 BeanB 实例化好才能完成构造,BeanB 又要等 BeanC,BeanC 等 BeanA。这样就形成了死循环,所以对于以构造器注入方式的循环依赖是无解的,Spring 容器会直接报异常。对于 setter 类型注入的循环依赖则可以顺利完成实例化并依次注入
(针对第六步)BeanPostProcessor 是一个很有用的接口,通过实现接口我们就可以插手 bean 的实例化过程,为拓展提供了可能。我们所熟知的 AOP 就是在这里进行织如入,具体点说是在 postProcessAfterInitialization(Object bean, String beanName) 执行织入逻辑的。
下面就来说说 Spring AOP 织入的流程,以及 AOP 是怎样和 IOC 整合的。
先说 Spring AOP 织入流程,大致如下:
(1)查找实现了 PointcutAdvisor 类型的切面类,切面类包含了 Pointcut 和 Advice 实现类对象。
(2)检查 Pointcut 中的表达式是否能匹配当前 bean 对象。
(3)如果匹配到了,表明应该对此对象织入 Advice。
将 bean,bean class对象,bean实现的interface的数组,Advice对象传给代理工厂 ProxyFactory。代理工厂创建出 AopProxy 实现类,最后由 AopProxy 实现类创建 bean 的代理类,并将这个代理类返回。此时从 postProcessAfterInitialization(Object bean, String beanName) 返回的 bean 此时就不是原来的 bean 了,而是 bean 的代理类。原 bean 就这样被无感的替换掉了,是不是有点偷天换柱的感觉。
AOP 是怎样和 IOC 整合起来并协同工作的呢?
Spring AOP 生成代理类的逻辑是在 AbstractAutoProxyCreator 相关子类中实现的,比如 DefaultAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator 等。上面说了 BeanPostProcessor 为拓展留下了可能,这里 AbstractAutoProxyCreator 就将可能变为了现实。AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口,这样 AbstractAutoProxyCreator 可以在 bean 初始化时做一些事情。光继承这个接口还不够,继承这个接口只能获取 bean,要想让 AOP 生效,还需要拿到切面对象(包含 Pointcut 和 Advice)才行。所以 AbstractAutoProxyCreator 同时继承了 BeanFactoryAware 接口,通过实现该接口,AbstractAutoProxyCreator 子类就可拿到 BeanFactory,有了 BeanFactory,就可以获取 BeanFactory 中所有的切面对象了。有了目标对象 bean,所有的切面类,此时就可以为 bean 生成代理对象了。
原文地址:https://www.cnblogs.com/BaoZiY/p/11376326.html
- MySQL中的derived table(r12笔记第47天)
- Oracle数据库端口突然无法访问的分析(r12笔记第46天)
- MySQL中的反连接(r12笔记第45天)
- Nginx配置多站点下的Proxy_cache或Fastcgi_cache缓存加速
- MySQL主从不一致的细小问题分析(r12笔记第62天)
- Linux在批量服务器管理中实用的PS1命令提示符格式
- Golang语言社区-并发模型和应用场景
- 翻过那座山,就能看见海|kubernetes让DBA更优雅地管理数据库
- 基于TextCNN的谩骂评论识别模型
- Golang语言社区-文件操作
- MySQL service启动脚本浅析(r12笔记第59天)
- 分享WordPress显示评论者IP的归属地及运营商信息的2种方案
- 解决dos2unix/unix2dos报错,并在家目录下生成u2dtmp*文件问题
- 【前沿】TensorFlow Pytorch Keras代码实现深度学习大神Hinton NIPS2017 Capsule论文
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- leetcode周赛(195)
- Scrapy:修改User-Agent方法
- Pycharm 一键加引号
- 单词搜索
- JVM运行时数据区
- 最长重复子数组
- 编辑距离
- 有序矩阵中第K小的元素
- nodejs库yaml读取yml或yaml配置文件
- 爬虫小白:03.requests的使用
- Oracle GoldenGate 19 Microservices数据同步实战与故障处理
- 给“小白”漫画+图示讲解MyBatis原理,就问香不香!
- webClientTest 编写单元测试类
- 关于gorm多表联合查询(left join)的小记
- UnicodeEncodeError: 'latin-1' codec can't encode character 'u2026' in position 30: ordinal not i...