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由浅入深相关推荐

  1. 为什么需要Spring? 什么是Spring?带你由浅入深的方式进行介绍,只要你会编程就能看懂

    前言 为什么需要Spring? 什么是Spring? 对于这样的问题,大部分人都是处于一种朦朦胧胧的状态,说的出来,但又不是完全说的出来,今天我们就以架构设计的角度尝试解开Spring的神秘面纱. 本 ...

  2. DBA入门之路:由浅入深的总结学习法

    有很多DBA朋友在入门时总觉得不得路径,长久的徘徊于门外,而过来人的经验又往往高屋建瓴难以落地,两者总觉得难以对接起来,如何才能解决这个问题呢? 我一直推荐的学习方法,之前在文章 DBA入门之路:学习 ...

  3. Spring BeanDefinitionRegistryPostProcessor BeanPostProcessor作用

    写博客,写博客,把自己知道的小知识点全部记录,? BeanDefinitionRegistryPostProcessor 接口属于Beanddefination  装配定义的范畴,此时bean 并没有 ...

  4. JSP由浅入深(1)—— 熟悉JSP服务器

    本"JSP由浅入深" 系列教程是面向中级和高级用户的,它需要HTML和Java的基础.你应该会将HTML网页连接到一起,并且会利用Java来进行编程.如果你还没有这个基础,建议你还 ...

  5. 由浅入深CIL系列【目录索引】+ PostSharp AOP编程【目录索引】

    CIL简介:CIL(Common Intermediate Language)中文名为通用中间语言,注意它曾经被称为微软中间语言或MSIL,它是一种类似于JAVA字节码的语言.在微软语言平台中,不管程 ...

  6. 由浅入深之Tensorflow(3)----数据读取之TFRecords

    由浅入深之Tensorflow(3)----数据读取之TFRecords 转载自http://blog.csdn.net/u012759136/article/details/52232266 原文作 ...

  7. 哪本python入门书内容最详细-重磅 | 由浅入深的 AI 学习路线,最详细的资源整理!...

    原标题:重磅 | 由浅入深的 AI 学习路线,最详细的资源整理! [导读] 本文由知名开源平台,AI技术平台以及领域专家: Datawhale, ApacheCN, AI有道和 黄海广博士联合整理贡献 ...

  8. python基础知识面试题-Python基本面试解答由浅入深—简答题

    原标题:Python基本面试解答由浅入深-简答题 不管你是学习任何语言,不管你是刚毕业还是行业大佬,找工作最终逃不掉的就是面试题,有的程序员很讨厌面试题,他们觉得面试题不会不代表我做不出东西,其实这种 ...

  9. spring中的BeanPostProcessor

    1.类结构 BeanPostProcessor:允许自定义修改bean实例的工厂钩子 InstantiationAwareBeanPostProcessor:BeanPostProcessor的子接口 ...

最新文章

  1. 汕头金山中学2021高考成绩查询,2019汕头市金山中学录取分数线及2019高考成绩喜报...
  2. 免费教材丨第47期:业界大牛中文教学视频《深度学习:进阶》第21-24讲
  3. Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
  4. cocos2dx对所有子节点设置透明度
  5. CentOS 7 + MySql 中文乱码解决方案
  6. ABAP从数据库中删除行
  7. Java虚拟机性能管理神器 - VisualVM(2) 入门
  8. java环境变量的配置_Java的下载及环境变量的配置
  9. WSAAsyncSelect() 非阻塞模式WinSock
  10. 【BZOJ-2888】资源运输 LCT + 启发式合并
  11. 网页跳转,转,出自:秋实的日积月累
  12. [AutoSAR]NXP HS12(X) AUTOSAR MCAL编译一下
  13. nc系统java不能用_用友NC管理系统使用过程中常见问题和解决方法!
  14. libxml2的安装及使用
  15. Web前端开发 -- HTML基础(2)
  16. 三菱伺服驱动器MR-JE CN3号串口线连接
  17. Web 实现登录记住密码功能
  18. 从零开始SpringCloud Alibaba实战(47)——阿里开发手册泰山版学习笔记一 命名风格
  19. Arduino安全和警报系统项目
  20. snapchat忘记账户_如何删除您的Snapchat帐户

热门文章

  1. ​微信小程序 获取地理位置(显示地图并显示经纬度)​
  2. I帧和IDR帧的区别
  3. 解决支付宝验证失败sign check fail: check Sign and Data Fail
  4. 视频怎么转文字?快把这些方法收好
  5. 软件开发模式:瀑布与敏捷应用思考
  6. java 图片背景色_java处理图片背景颜色的方法
  7. 静态库与共享库制作,及区别
  8. Quartz配置上次任务没有执行完,下次任务推迟执行
  9. 债券价格和到期收益率的关系_债券价格与到期收益率之间的关系.PPT
  10. 重装也无法修复此计算机,win10系统重置此电脑失败怎么解决