BeanPostProcessor —— 连接Spring IOC和AOP的桥梁
之前都是从大Boss的视角,来介绍Spring,比如IOC、AOP。
今天换个视角,从一个小喽啰出发,来加深对Spring的理解。
这个小喽啰就是, BeanPostProcessor (下面简称 BBP )。
讲解思路:
- BBP怎么用 —— 先学会怎么用,再去看原理
- BBP的触发时机 —— 在整个Spring Bean初始化流程中的位置
- BBP自己又是什么时候被创建的?
- BBP是如何连接IOC和AOP的?
怎么用
BeanPostProcessor,直译过来,就是“对象后处理器”, 那么这个“后”,是指什么之后呢?
试试便知。
我们先写一个对象,Bean4BBP( 本文的所有代码,可到 Github 上下载 ):
@Component public class Bean4BBP {private static final Logger log = LoggerFactory.getLogger(Bean4BBP.class);public Bean4BBP(){log.info("construct Bean4BBP");} }
然后再写一个BeanPostProcessor,这时发现它是一个接口,没关系,那就写一个类实现它,CustomBeanPostProcessor:
@Component public class CustomBeanPostProcessor implements BeanPostProcessor {private static final Logger log = LoggerFactory.getLogger(CustomBeanPostProcessor.class);public CustomBeanPostProcessor() {log.info("construct CustomBeanPostProcessor");}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Bean4BBP) {log.info("process bean before initialization");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Bean4BBP) {log.info("process bean after initialization");}return bean;} }
然后启动我们的Spring Boot项目(直接运行Application类),看这几条日志打印的顺序:
construct CustomBeanPostProcessor construct Bean4BBP process bean before initialization process bean after initialization
BBP对象首先被创建,然后创建Bean4BBP对象,接着再先后执行BBP对象的postProcessBeforeInitialization和postProcessAfterInitialization方法。
结论:“对象后处理器”,指的是“ 对象创建后处理器 ”。
我们可以利用它,在对象创建之后,对对象进行修改(有什么场合需要用到?思考题,文末回答。)
那么,为什么要分postProcessBeforeInitialization和postProcessAfterInitialization呢?这里的Initialization是什么意思?
触发时机
我们只需要在CustomBeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法里,打上两个断点,一切自然明了。
断点进来,跟着调用栈这点蛛丝马迹往回走,真相大白:
在initializeBean方法里面,先后调用了applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法,这两个方法内部,则分别去遍历系统里所有的BBP,然后逐个执行这些BBP对象的postProcessBeforeInitialization和postProcessAfterInitialization方法,去处理对象,以applyBeanPostProcessorsBeforeInitialization为例:
那么夹在applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法中间的invokeInitMethods方法是做什么的呢?
其实这个方法就是Spring提供的,用于对象创建完之后,针对对象的一些初始化操作。这就好比你创建了一个英雄之后,你需要给他进行一些能力属性的初始化、服装初始化一样。
要验证这一点,很简单,只需让Bean4BBP实现InitializingBean接口:
@Component public class Bean4BBP implements InitializingBean {private static final Logger log = LoggerFactory.getLogger(Bean4BBP.class);public Bean4BBP(){log.info("construct Bean4BBP");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("init Bean4BBP");} }
然后重新启动工程,打印顺序如下:
construct CustomBeanPostProcessor construct Bean4BBP process bean before initialization init Bean4BBP process bean after initialization
BBP是什么时候被初始化的
从上面的代码片段,我们已经知道,在对象创建之后,需要遍历BBP列表,对对象进行处理。
这也就意味着, BBP对象,必须在普通对象创建之前被创建 。
那么BBP都是在什么时候被创建的呢?
要回答这个问题,非常简单, 我们只需要在CustomBeanPostProcessor的构造函数里打个断点 (这下看到先学会用,再了解原理的好处了吧)
断点进来,继续利用调用栈,我们找寻到了AbstractApplicationContext的refresh()方法,这个方法里面调用了registerBeanPostProcessors方法,里头就已经把BBP列表创建好了,而普通对象的创建,是在之后的finishBeanFactoryInitialization方法里执行的:
网上有个图画的特别好,很好的展示了BBP在Spring对象初始化流程的位置:
(看到BBP在哪了吗?)
BBP的典型使用 - AOP
不知道大家在使用Spring AOP时,有没有发现,带有切面逻辑的对象,注入进来之后,都不是原来的对象了,比如下图:
调试信息显示,aspectService是一个…$$EnhanceBySpringCGlib的对象,这其实和Spring AOP用到的动态代理有关。
关于Spring AOP的原理,可以参考我之前的回答: 什么是面向切面编程AOP? - Javdroider Hong的回答 - 知乎
这也就意味着, 最终放进Spring容器的,必须是代理对象,而不是原先的对象 ,这样别的对象在注入时,才能获得带有切面逻辑的代理对象。
那么Spring是怎么做到这一点的呢?正是利用了这篇文章讲到的BBP。
显然,我只需要写一个BBP,在postProcessBeforeInitialization或者postProcessAfterInitialization方法中,对对象进行判断,看他需不需要织入切面逻辑,如果需要,那我就根据这个对象,生成一个代理对象,然后返回这个代理对象,那么最终注入容器的,自然就是代理对象了。
这个服务于Spring AOP的BBP,叫做 AnnotationAwareAspectJAutoProxyCreator .
利用idea的diagram功能,可以看出它和BBP的关系:
具体的创建代理对象并返回的逻辑,在postProcessAfterInitialization方法中,大家自行欣赏。
可以说,如果没有BBP,那么Spring AOP就只能叫AOP。
BBP是连接IOC和AOP的桥梁。
总结
这篇文章,主要通过对BBP的讲解,串联起之前讲到的关于Spring的知识,希望能够加深大家对Spring的理解。
最后,回到开头提出的四个问题:
- BBP怎么用 —— 先学会怎么用,再去看原理
- BBP的触发时机 —— 在整个Spring Bean初始化流程中的位置
- BBP自己又是什么时候被创建的?
- BBP是如何连接IOC和AOP的?
转载于:https://www.cnblogs.com/yuxiang1/p/9199730.html
BeanPostProcessor —— 连接Spring IOC和AOP的桥梁相关推荐
- 自己动手实现的 Spring IOC 和 AOP - 下篇
1. 背景 本文承接上文,来继续说说 IOC 和 AOP 的仿写.在上文中,我实现了一个很简单的 IOC 和 AOP 容器.上文实现的 IOC 和 AOP 功能很单一,且 IOC 和 AOP 两个模块 ...
- 自己动手实现的 Spring IOC 和 AOP - 上篇
1. 背景 我在大四实习的时候开始接触 J2EE 方面的开发工作,也是在同时期接触并学习 Spring 框架,到现在也有快有两年的时间了.不过之前没有仿写过 Spring IOC 和 AOP,只是宏观 ...
- 【Spring 源码阅读】Spring IoC、AOP 原理小总结
Spring IoC.AOP 原理小总结 前言 版本约定 正文 Spring BeanFactory 容器初始化过程 IoC 的过程 bean 完整的创建流程如下 AOP 的过程 Annotation ...
- 浅谈 Spring IOC和AOP
浅谈 Spring IOC和AOP IOC 控制反转 以前创建对象的主动权和时机是由于自己把握的,现在将这种权利转移到Spring容器中,并且根据配置文件去创建对象管理对象 ioc的注入方式有三种:构 ...
- Spring IoC 和 AOP
Spring IoC 和 AOP spring框架java开发的行业标准. spring全家桶. Web:Spring Web MVC/Spring MVC,Spring Web Flux 持久层:S ...
- 再品Spring Ioc 和 Aop
文章目录 Spring好处 IOC 基于XML和基于注解开发 基于XML开发 基于注解开发 配置类 扫包+注解 依赖注入 AOP 写在前面,这篇文章写的时候我的SSM已经学过一遍了,回头来看真的受益匪 ...
- 吊打面试官系列之--吃透Spring ioc 和 aop (中)
目录 Spring SpringBean的五个作用域 SpringBean的生命周期 创建过程 销毁过程 AOP的介绍和使用 AOP的介绍 AOP的三种织入方式 操作讲解 AOP的主要名词概念 Adv ...
- 抛弃隐晦,明了的理解Spring IOC与AOP
IOC(反转控制) 一个java应用程序是有很多类组成的,这些类相互协作.相互作用来提供应用程序的表现行为.那些被其它类组合提供某些行为的类,称之为其它类的依赖(dependencies).利用软件工 ...
- Spring IOC 和 AOP 概览
IOC(控制反转) IoC(Inversion of Control,控制倒转).所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系. 在没有IOC时,我们 ...
最新文章
- 极验行为验证的使用方法
- Azure PowerShell (6) 设置单个Virtual Machine Endpoint
- c语言程序窗口后台持续监测,用c语言实现后台运行的、每隔30s检查一次的、带有日志功能的断网重新连接程序...
- 【数据迁移】使用传输表空间迁移数据
- 【MCtalk活动推荐】IM快速搭建即时通讯实战
- ABAP开发环境语法高亮的那些事儿
- mysql的联表查询和去重复数据
- 微信小程序 WXBizDataCrypt 解密 报错
- [转载] python与c/c++相比有哪些优势
- 关于table的那些用法(一)
- HTTP代理实现请求报文的拦截与篡改2--功能介绍+源码下载
- java socket 全双工_java socket实现全双工通信
- 关于系统响应函数OnSysCommand
- C# 获取Newtonsoft.Json的JObject多层节点内容
- Ubuntu18.04安装WPS
- php怎么将农历转换成公历,PHP 实现公历日期与农历日期的互转换
- 新人如何快速融入团队
- 为什么html中使用不了样式,css不起作用是什么原因?
- 论文阅读:Reasoning about Object Affordances in a Knowledge Base Representation
- To https://gitee.com/xxxx/gittest.git解决方案