BeanPostProcessor由浅入深
BeanPostProcessor由浅入深:
1、BeanPostProcessor原理:
该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。流程图如下(如何使用这里就不附上代码,相信大家已经了解)
首先-初始化bean—>检查容器中是否存在BeanPostProcessor,
如果存在就调用postProcessBeforeInitialization方法
.
—>如果返回null(或者所有的BeanPostProcessor执行完毕)
.
---->执行bean的初始化方法
.
---->再次判断容器中是否存在BeanPostProcessor
.
—>如果存在就调用postProcessAfterInitialization方法
.
—>如果返回null(或者所有的BeanPostProcessor执行完毕)
.
—>运行结束
如果一开始容器中就没有 BeanPostProcessor,那么就会直接支持bean的初始化方法,结束;(结合流程与源码一起会更加清晰,下附源码)
2、容器启动到Bean创建–底层源码流程:
test方法----…---->refresh()
---->finishBeanFactoryInitialization()
.
---->preInstantiateSingletons()
.
---->preInstantiateSingletons()
.
---->getBean()
.
---->doGetBean()
.
----> getSingleton(beanName, new ObjectFactory()
这是一个简单的流程,可以大致看一下在容器启动的时候具体调用了哪些方法;我们先进入doGetBean方法里面:发现其实是调用了getSingleton方法获取实例,
如果没有获取到又通过getObject()里面的 createBean(beanName, mbd, args)创建实例,总之这个实例一定要创建出来
因为长度问题这里只取这篇文章对最关键的一部分展示(谅解一下)
doGetBean()
.....................................................
if (mbd.isSingleton()) {// 获取单实例bean 获取不到的话就通过getObject()里面的 createBean(beanName, mbd, args); 创建实例sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Overridepublic Object getObject() throws BeansException {try {return createBean(beanName, mbd, args); }catch (BeansException ex) {destroySingleton(beanName);throw ex;}}});createBean(beanName, mbd, args)里面实际又调用 Object beanInstance = doCreateBean(beanName, mbdToUse, args) 创建实例 并用Object接收
3、让我们看看doCreateBean是如何创建bean实例的:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;...........................................................Object exposedObject = bean;try {//在里面进行各种判断为属性赋值,先为属性赋值,下面再调用initializeBean()populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {//后置处理器的调用,以及bean的初始化都在此被执行(ง •_•)ง ,后面进入initializeBean方法exposedObject = initializeBean(beanName, exposedObject, mbd);}}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}...........................................................return exposedObject;}
4、initializeBean方法(也就是BeanPostProcessor最关键的执行步骤):
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {invokeAwareMethods(beanName, bean);return null;}}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {**// 1. 应用后处理器的BeforeInitialization方法**wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {**//调用bean的初始化方法**invokeInitMethods(beanName, wrappedBean, mbd); **ini-method**}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {**// 3. 调用后处理器的AfterInitialization方法**wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}}
可以看到,初始化方法是在BeanPostProcessor执行之后才执行的,下面让我们了解一下applyBeanPostProcessorsBeforeInitialization具体是如何获取,并执行的
5、applyBeanPostProcessorsBeforeInitialization:
进入方法,首先通过foreach遍历容器中得到的所有BeanPostProcessor;挨个执行beforeInitialization,
一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization(同理applyBeanPostProcessorsAfterInitialization也是如此)
@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {//初始化之前按调用了BeforeInitialization方法result = beanProcessor.postProcessBeforeInitialization(result, beanName);if (result == null) {return result;}}return result;}
3、总的来说,就是再doCreateBean创建bean的时候调用了populateBean(beanName, mbd, instanceWrapper)方法给bean进行属性赋值。
⭐(细节问题:一定时先给bean属性赋值,再调用的BeanPostProcessor,初始化方法)在属性赋值以后调用了初始化bean的方法initializeBean
在initializaBean里面就调用了后置处理器,可以发现,BeanPostProcessor是在初始化方法前后调用的(ini-method)
{1- applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);2- invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化3- applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}
6、尾:
谈一下BeanPostProcessor及其子类:(这里只涉及一下ApplicationContextAwareProcessor)
1、InitDestroyAnnotationBeanPostProcessor
处理初始化方法(我们初始化方法是如何执行的,如何被容器发现的,都是因为这个组件在工作,可在int-method打断点看看具体调试)
2、AutowiredAnnotationBeanPostProcessor
处理自动装配,为什么Spring可以自动装配呢,当然是因为有这个类了,这里就不多说。
3、BeanValidationPostProcessor主要是用来数据校验,一般在MVC里面用的比较多
4、ApplicationContextAwareProcessor 作用是帮我们组件里面注入IOC容器 如何注入呢?看代码
只需要实现ApplicationContextAware接口,并且重写setApplicationContext方法,再将ApplicationContext对象传入即可
@Component
public class Dog implements ApplicationContextAware { //@Autowiredprivate ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// TODO Auto-generated method stubthis.applicationContext = applicationContext;}走一下源码:
从initializeBean初始化bean的时候里面调用了applyBeanPostProcessorsBeforeInitialization--->postProcessBeforeInitialization--->invokeAwareInterfaces@Overridepublic Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { 在这里进行了判断,判断是否实现了ApplicationContextAware以及这些其他的的接口acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {invokeAwareInterfaces(bean); 如果是的话就调用invokeAwareInterfaces给里面注入值,怎么注入的,看下面的方法;(虽然是if语句,但是都会进行判断,注意细节)return null;}}, acc);}else {invokeAwareInterfaces(bean);}return bean;}
注入:private void invokeAwareInterfaces(Object bean) { 判断是哪个Aware,那把哪个Aware注入进去if (bean instanceof Aware) {if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}if (bean instanceof ApplicationContextAware) {
这里我们是ApplicationContextAware,所以直接把bean强转ApplicationContextAware再调用setApplicationContext,直接把IOC容器注入进去,然后就实现了向组件里面注入ioc容器了((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}
如果哪里不足,还请指出,大家一起共同进步(^ _^),加油。 ##BeanPostProcessor原理由浅入深
BeanPostProcessor由浅入深相关推荐
- 为什么需要Spring? 什么是Spring?带你由浅入深的方式进行介绍,只要你会编程就能看懂
前言 为什么需要Spring? 什么是Spring? 对于这样的问题,大部分人都是处于一种朦朦胧胧的状态,说的出来,但又不是完全说的出来,今天我们就以架构设计的角度尝试解开Spring的神秘面纱. 本 ...
- DBA入门之路:由浅入深的总结学习法
有很多DBA朋友在入门时总觉得不得路径,长久的徘徊于门外,而过来人的经验又往往高屋建瓴难以落地,两者总觉得难以对接起来,如何才能解决这个问题呢? 我一直推荐的学习方法,之前在文章 DBA入门之路:学习 ...
- Spring BeanDefinitionRegistryPostProcessor BeanPostProcessor作用
写博客,写博客,把自己知道的小知识点全部记录,? BeanDefinitionRegistryPostProcessor 接口属于Beanddefination 装配定义的范畴,此时bean 并没有 ...
- JSP由浅入深(1)—— 熟悉JSP服务器
本"JSP由浅入深" 系列教程是面向中级和高级用户的,它需要HTML和Java的基础.你应该会将HTML网页连接到一起,并且会利用Java来进行编程.如果你还没有这个基础,建议你还 ...
- 由浅入深CIL系列【目录索引】+ PostSharp AOP编程【目录索引】
CIL简介:CIL(Common Intermediate Language)中文名为通用中间语言,注意它曾经被称为微软中间语言或MSIL,它是一种类似于JAVA字节码的语言.在微软语言平台中,不管程 ...
- 由浅入深之Tensorflow(3)----数据读取之TFRecords
由浅入深之Tensorflow(3)----数据读取之TFRecords 转载自http://blog.csdn.net/u012759136/article/details/52232266 原文作 ...
- 哪本python入门书内容最详细-重磅 | 由浅入深的 AI 学习路线,最详细的资源整理!...
原标题:重磅 | 由浅入深的 AI 学习路线,最详细的资源整理! [导读] 本文由知名开源平台,AI技术平台以及领域专家: Datawhale, ApacheCN, AI有道和 黄海广博士联合整理贡献 ...
- python基础知识面试题-Python基本面试解答由浅入深—简答题
原标题:Python基本面试解答由浅入深-简答题 不管你是学习任何语言,不管你是刚毕业还是行业大佬,找工作最终逃不掉的就是面试题,有的程序员很讨厌面试题,他们觉得面试题不会不代表我做不出东西,其实这种 ...
- spring中的BeanPostProcessor
1.类结构 BeanPostProcessor:允许自定义修改bean实例的工厂钩子 InstantiationAwareBeanPostProcessor:BeanPostProcessor的子接口 ...
最新文章
- 汕头金山中学2021高考成绩查询,2019汕头市金山中学录取分数线及2019高考成绩喜报...
- 免费教材丨第47期:业界大牛中文教学视频《深度学习:进阶》第21-24讲
- Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
- cocos2dx对所有子节点设置透明度
- CentOS 7 + MySql 中文乱码解决方案
- ABAP从数据库中删除行
- Java虚拟机性能管理神器 - VisualVM(2) 入门
- java环境变量的配置_Java的下载及环境变量的配置
- WSAAsyncSelect() 非阻塞模式WinSock
- 【BZOJ-2888】资源运输 LCT + 启发式合并
- 网页跳转,转,出自:秋实的日积月累
- [AutoSAR]NXP HS12(X) AUTOSAR MCAL编译一下
- nc系统java不能用_用友NC管理系统使用过程中常见问题和解决方法!
- libxml2的安装及使用
- Web前端开发 -- HTML基础(2)
- 三菱伺服驱动器MR-JE CN3号串口线连接
- Web 实现登录记住密码功能
- 从零开始SpringCloud Alibaba实战(47)——阿里开发手册泰山版学习笔记一 命名风格
- Arduino安全和警报系统项目
- snapchat忘记账户_如何删除您的Snapchat帐户
热门文章
- ​微信小程序 获取地理位置(显示地图并显示经纬度)​
- I帧和IDR帧的区别
- 解决支付宝验证失败sign check fail: check Sign and Data Fail
- 视频怎么转文字?快把这些方法收好
- 软件开发模式:瀑布与敏捷应用思考
- java 图片背景色_java处理图片背景颜色的方法
- 静态库与共享库制作,及区别
- Quartz配置上次任务没有执行完,下次任务推迟执行
- 债券价格和到期收益率的关系_债券价格与到期收益率之间的关系.PPT
- 重装也无法修复此计算机,win10系统重置此电脑失败怎么解决