Spring IOC学习心得之BeanPostProcessor,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口是如何起作用的
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接口是如何起作用的相关推荐
- Spring IOC学习心得之Bean对IOC容器的感知
容器管理的Bean一般不需要了解容器的状态和直接使用Bean,但是在某些情况下,是需要在Bean中直接对IOC容器进行操作的,这时候,就需要在Bean中设定对容器的感知.Spring IOC也提供了该 ...
- Spring IOC学习心得之源码级分析ContextLoaderListener的作用(IOC容器初始化入口)
ContextLoaderListener类是负责初始化IOC容器,即在我们的web项目中,这里就是IOC容器初始化的入口,由这个类启动IOC容器的初始化. 它配置在web.xml中,比如如下配置: ...
- Spring IOC学习心得之IOC容器的初始化过程
注:本文大多数内容都是摘自<Spring技术内幕>这本书 简单来说,Ioc容器的初始化过程是在refresh()方法中启动的,包括BeanDefinition的Resource定位,载入和 ...
- Spring IOC学习心得之注册bean的依赖关系
registerDependentBean方法的解析(注册bean的依赖关系) 源码如下: public void registerDependentBean(String beanName, Str ...
- BT源代码学习心得(五):统一网络服务接口--RawServer -- 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(五):统一网络服务接口--RawServer author:wolfenstein 以后的部分都需要网络服务(种子文件的生成在本地就可以完成,但是通过这些种子文件下载实际的内容和提 ...
- 关于spring IoC 学习
What is IoC 简单来说: 控制:当前对象对其内部成员对象的控制权/获取组装对象的过程 反转:上述的过程/控制权,交由专门的第三方组件(容器或者说平台)来管理 这种从具体对象手中,交出控制的做 ...
- Spring IOC 学习总结
1 什么是IOC.DI IoC-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制 ...
- 【Spring】Spring IOC学习笔记
Spring IOC Spring简介 Spring理念 使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架 Spring优点 Spring是一个轻量级的 控制反转(IOC) 和 面向切 ...
- Spring IoC 学习(3)
前言 前面因为总结的累了,把IoC的两个步骤,只写了一半,就仅仅把容器启动的方面说了说,对于实例化的阶段,我前面并没有说,在这节中,准备讲一讲,实例化阶段. 生命周期 基础生命周期简图 这个部分,其实 ...
最新文章
- sqoop导入数据到hive中元数据问题
- PyQt4编程之简短地做出多个选择框
- Axure 安装使用说明
- mysql两个表查询修改_MySQL:查询、修改(二)
- CMake 常用命令和变量
- JavaScript 的 switch 条件语句
- 简单使用mybatis(idea中使用)
- 服装ERP管理软件有哪些功能
- html5时间插件mui,移动端时间控件 HTML5+ 的 pickDate 和 MUI 的 dtpicker 的使用与对比...
- 深度linux显示方块,在Deepin下用Wine运行文华财经赢顺的经验,附字体显示方框的解决...
- Windows10 无法使用内置管理员打开照片问题解决
- js以excel为模板的打印
- 玩转基因组浏览器之初识IGV
- 全国女人都当妓女的古代神秘国(转载)
- python绘制随机网络图形
- 2020云米5G战略新品发布,超越时代探索“互联未来•互动家”
- nimi SearchEngin 项目思路及算法
- 物流ERP软件测试行业,简单说说ERP测试
- 玩转ERP:一句话介绍一下SAP CS模块
- CSS 实现“故障”特效
热门文章
- js数据类型 方法 函数
- SpringMVC使用ModelAndView进行重定向
- H5实现俄罗斯方块(一)
- Cocos2d-3.x Android环境搭建
- 修改ECSHOP后台的商品列表里显示该商品品牌
- 支持位移操作的环形字符串
- java fields是_一个快速生成R2.java中fields的插件
- 在C 编程语言中 静态数组的替代模板,以编译方式在C ++中编译时创建静态数组...
- 今天讲个小故事,Javascript诞生记
- Java解析SQL生成语法树_Atitit.sql ast 表达式 语法树 语法 解析原理与实现 java php c#.net js python...