1. 首先说下BeanPostProcessor接口中的两个方法,如下:

package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;public interface BeanPostProcessor {//Bean初始化的前置处理器Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//Bean初始化的后置处理器Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}

应用中自定义的Bean,可以实现这个接口,并覆盖这两个方法来控制Bean的初始化过程,即在Bean的初始化之前做一件事,即调用postProcessBeforeInitialization方法,也可以在Bean的初始化之后做一件事,即调用postProcessAfterInitialization方法。那么这两个方法究竟是如何被Spring调用的呢?

2. 在Bean的初始化过程中,会调用initializeBean方法,该方法的源码如下:

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()) {//执行BeanPostProcessor扩展点的PostProcessBeforeInitialization进行修改实例化BeanwrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method属性指定的//同时,如果Bean实现了InitializingBean接口,那么这个Bean的afterPropertiesSet实现也不会被调用invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {//执行BeanPostProcessor扩展点的PostProcessAfterInitialization进行修改实例化BeanwrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

3. BeanPostProcessor起作用的方式

先说下invokeInitMethods方法,这个是真正的Bean的初始化方法,我们可以看到在该方法之前有一个方法applyBeanPostProcessorsBeforeInitialization,该方法实现Bean初始化的前置处理,可以看下该方法的源码:

@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessBeforeInitialization(result, beanName);if (result == null) {return result;}}return result;}

这个方法中会通过getBeanPostProcessors方法去获取Bean所实现的所有的BeanPostProcessor接口,并调用其postProcessBeforeInitialization方法来实现在Bean的初始化之前做一些预处理

在invokeInitMethods方法之后,有一个applyBeanPostProcessorsAfterInitialization方法,该方法实现Bean的初始化的后置处理,可以看下该方法的源码:

@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessAfterInitialization(result, beanName);if (result == null) {return result;}}return result;}

与前置处理类似,也是获取Bean实现的所有BeanPostProcessor接口,然后调用所有接口的postProcessAfterInitialization后置处理方法

4.  BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口起作用的方式

大家注意到initializebean方法中有一个invokeAwareMethods方法,先看下这个方法的源码:

private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}

举例来说,当应用自定义的Bean实现了BeanNameAware接口,如下:

public class MyBean implements BeanNameAware {private String beanName;void setBeanName(String name) {this.beanName = name;}}

这样就可以获取到该Bean在Spring容器中的名字,原理就是上述invokeAwareMethods方法中,判断了如果bean实现了BeanNameAware接口,就会调用该Bean覆盖的BeanNameAware接口的setBeanName方法,这样MyBean中就获取到了该Bean在Spring容器中的名字。

BeanClassLoaderAware接口和BeanFactoryAware接口同理,可以分别获取Bean的类装载器和bean工厂

5. InitializeBean接口起作用的方式

最后来说下真正的初始化方法invokeInitMethods,该方法的源码如下:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isDebugEnabled()) {logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {((InitializingBean) bean).afterPropertiesSet();return null;}}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {((InitializingBean) bean).afterPropertiesSet();   //启动afterPropertiesSet,afterPropertiesSet是InitializingBean接口的方法}}if (mbd != null) {String initMethodName = mbd.getInitMethodName();   //获取用户自定义的初始化方法if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {invokeCustomInitMethod(beanName, bean, mbd);    //调用自定义的初始化方法}}

可以看到方法中判断了如果该Bean实现了InitializeBean接口,即bean instanceof InitializingBean == true,就会调用该Bean实现的Initializebean接口的afterPropertiesSet方法

6. 自定义的初始化方法起作用的方式

上述代码中有一个方法getInitMethodName,可以获取用户自定义的初始化方法,然后通过调用invokeCustomInitMethod方法来执行用户自定义的初始化方法

Spring IOC学习心得之BeanPostProcessor,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口是如何起作用的相关推荐

  1. Spring IOC学习心得之Bean对IOC容器的感知

    容器管理的Bean一般不需要了解容器的状态和直接使用Bean,但是在某些情况下,是需要在Bean中直接对IOC容器进行操作的,这时候,就需要在Bean中设定对容器的感知.Spring IOC也提供了该 ...

  2. Spring IOC学习心得之源码级分析ContextLoaderListener的作用(IOC容器初始化入口)

    ContextLoaderListener类是负责初始化IOC容器,即在我们的web项目中,这里就是IOC容器初始化的入口,由这个类启动IOC容器的初始化. 它配置在web.xml中,比如如下配置: ...

  3. Spring IOC学习心得之IOC容器的初始化过程

    注:本文大多数内容都是摘自<Spring技术内幕>这本书 简单来说,Ioc容器的初始化过程是在refresh()方法中启动的,包括BeanDefinition的Resource定位,载入和 ...

  4. Spring IOC学习心得之注册bean的依赖关系

    registerDependentBean方法的解析(注册bean的依赖关系) 源码如下: public void registerDependentBean(String beanName, Str ...

  5. BT源代码学习心得(五):统一网络服务接口--RawServer -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(五):统一网络服务接口--RawServer author:wolfenstein 以后的部分都需要网络服务(种子文件的生成在本地就可以完成,但是通过这些种子文件下载实际的内容和提 ...

  6. 关于spring IoC 学习

    What is IoC 简单来说: 控制:当前对象对其内部成员对象的控制权/获取组装对象的过程 反转:上述的过程/控制权,交由专门的第三方组件(容器或者说平台)来管理 这种从具体对象手中,交出控制的做 ...

  7. Spring IOC 学习总结

    1 什么是IOC.DI IoC-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制 ...

  8. 【Spring】Spring IOC学习笔记

    Spring IOC Spring简介 Spring理念 使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架 Spring优点 Spring是一个轻量级的 控制反转(IOC) 和 面向切 ...

  9. Spring IoC 学习(3)

    前言 前面因为总结的累了,把IoC的两个步骤,只写了一半,就仅仅把容器启动的方面说了说,对于实例化的阶段,我前面并没有说,在这节中,准备讲一讲,实例化阶段. 生命周期 基础生命周期简图 这个部分,其实 ...

最新文章

  1. sqoop导入数据到hive中元数据问题
  2. PyQt4编程之简短地做出多个选择框
  3. Axure 安装使用说明
  4. mysql两个表查询修改_MySQL:查询、修改(二)
  5. CMake 常用命令和变量
  6. JavaScript 的 switch 条件语句
  7. 简单使用mybatis(idea中使用)
  8. 服装ERP管理软件有哪些功能
  9. html5时间插件mui,移动端时间控件 HTML5+ 的 pickDate 和 MUI 的 dtpicker 的使用与对比...
  10. 深度linux显示方块,在Deepin下用Wine运行文华财经赢顺的经验,附字体显示方框的解决...
  11. Windows10 无法使用内置管理员打开照片问题解决
  12. js以excel为模板的打印
  13. 玩转基因组浏览器之初识IGV
  14. 全国女人都当妓女的古代神秘国(转载)
  15. python绘制随机网络图形
  16. 2020云米5G战略新品发布,超越时代探索“互联未来•互动家”
  17. nimi SearchEngin 项目思路及算法
  18. 物流ERP软件测试行业,简单说说ERP测试
  19. 玩转ERP:一句话介绍一下SAP CS模块
  20. CSS 实现“故障”特效

热门文章

  1. js数据类型 方法 函数
  2. SpringMVC使用ModelAndView进行重定向
  3. H5实现俄罗斯方块(一)
  4. Cocos2d-3.x Android环境搭建
  5. 修改ECSHOP后台的商品列表里显示该商品品牌
  6. 支持位移操作的环形字符串
  7. java fields是_一个快速生成R2.java中fields的插件
  8. 在C 编程语言中 静态数组的替代模板,以编译方式在C ++中编译时创建静态数组...
  9. 今天讲个小故事,Javascript诞生记
  10. Java解析SQL生成语法树_Atitit.sql ast 表达式 语法树 语法 解析原理与实现 java php c#.net js python...