博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码分析:BeanPostProcessor原理
阅读量:7041 次
发布时间:2019-06-28

本文共 6445 字,大约阅读时间需要 21 分钟。

BeanPostProcessor即,Bean的后置处理器,它的作用就是在Bean的初始化方法前跟后进行拦截处理。我们都知道,要想在Bean的初始化方法前后进行工作,那必须在Bean实例创建完成之后,init方法执行之前,后置处理器就已经在容器中了,所以我们来到向容器中添加后置处理器的类AbstractApplicationContext,其中refresh()中的registerBeanPostProcessors(beanFactory)就是首先向容器中注册我们所需要的所有后置处理器。如何注册后置处理器我们暂不作分析,着重说一下,后置处理器是如何工作的。

代码实现

实现类:

@Componentpublic class BeanPostProcessorImpl implements BeanPostProcessor {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        // 返回一个传过来的对象        // 在初始化方法调用之前进行后置处理工作        // 什么时候调用呢?在init-method方法之前就调用了        System.out.println("postProcessBeforeInitialization======" + beanName + "======" + bean);        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("postProcessAfterInitialization======" + beanName + "======" + bean);        return bean;    }}

配置类:

@Configuration@ComponentScan("com.nmys.story.springCore.springioc.beanpostprocessor_")public class Config01 {    @Bean(initMethod = "init",destroyMethod = "destroy")    public Train train(){        return new Train();    }}

实体类:

/** * @author 70KG * @Title: Train * @Description: * @date 2018/7/23下午11:31 * @From www.nmyswls.com */public class Train {    private String name = "火车";    private Integer length = 150;    public Train() {        System.out.println("Train构造方法执行。。。。。。");    }    public void init() {        System.out.println("Train的init方法执行。。。。。。");    }    public void destroy() {        System.out.println("Train的destroy方法执行。。。。。。");    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getLength() {        return length;    }    public void setLength(Integer length) {        this.length = length;    }}

测试类:

public class Test01 {    @Test    public void test() {        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config01.class);        ac.close();    }}

打印结果:

Train构造方法执行。。。。。。postProcessBeforeInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4ebTrain的init方法执行。。。。。。postProcessAfterInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4ebTrain的destroy方法执行。。。。。。

结果分析:

首先Train构造方法执行创建对象,然后执行了后置处理器的Before方法,然后才调用init方法,init方法执行完成,再执行后置处理器的After方法,最后容器关闭执行销毁方法。

BeanPostProcessor原理分析

AnnotationConfigApplicationContext构造方法中的refresh();-> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩余Bean的初始化工作-> AbstractApplicationContext869行beanFactory.preInstantiateSingletons();-> DefaultListableBeanFactory760行getBean(beanName);-> AbstractBeanFactory317行createBean(beanName, mbd, args);-> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args);-> AbstractAutowireCapableBeanFactory580行populateBean(beanName, mbd, instanceWrapper);在执行初始化之前,首先给实例赋值-> AbstractAutowireCapableBeanFactory581行exposedObject = initializeBean(beanName, exposedObject, mbd);准备执行初始化方法-> AbstractAutowireCapableBeanFactory1700行wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);-> AbstractAutowireCapableBeanFactory1704行invokeInitMethods(beanName, wrappedBean, mbd);-> AbstractAutowireCapableBeanFactory1712行wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

分析AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法:

@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {    Object result = existingBean;    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {        Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);        if (current == null) {            return result;        }        result = current;    }    return result;}
  1. 首先获取到所有的后置处理器getBeanPostProcessors()
  2. 在for循环中依次调用后置处理器的方法beanProcessor.postProcessBeforeInitialization(result, beanName);
  3. 进入postProcessBeforeInitialization方法(这个方法必须在debug过程中才可以进入)
public 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)) {        acc = this.applicationContext.getBeanFactory().getAccessControlContext();    }    if (acc != null) {        AccessController.doPrivileged((PrivilegedAction) () -> {            invokeAwareInterfaces(bean);            return null;        }, acc);    }    else {        invokeAwareInterfaces(bean);    }    return bean;}

<!--more-->

private void invokeAwareInterfaces(Object bean) {    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).setApplicationContext(this.applicationContext);        }    }}
  1. 来到ApplicationContextAwareProcessor类的79行,首先判断此bean是不是各种的Aware,如果是它列举的那几个Aware就获取Bean工厂的权限,可以向容器中导入相关的上下文环境,目的是为了Bean实例能够获取到相关的上下文,如果不是(显然它也不是)它列举的几个Aware,那就调用invokeAwareInterfaces(bean),向容器中添加相关接口的上下文环境,显然我们自己的实现类也不属于Aware接口,所以这个处理结果直接将Bean返回,不做任何处理。ok,这样初始化之前的方法就分析完了,初始化之后的方法跟前面的流程一模一样。

总结

BeanPostProcessor就是在Bean实例创建之后,在进行populateBean赋值之后,init初始化方法之前进行一次调用,init方法之后进行一次调用,这样一来,整个Bean的生命周期,全部掌控在了Spring之下,包括Bean实例创建new Instance(),赋值前后populateBean(),初始化前后init(),销毁前后destroy()。从此Bean便身不由己了。

转载地址:http://dthal.baihongyu.com/

你可能感兴趣的文章
Codeforces Round #345 (Div. 2) D. Image Preview 暴力 二分
查看>>
suggest
查看>>
Java集合框架实现自定义排序
查看>>
数组添加:如何往数组的"null"位置插入数据呢?
查看>>
Number of Parallelograms(求平行四边形个数)
查看>>
转:基于TLS1.3的微信安全通信协议mmtls介绍
查看>>
ImageNet && 医学图像的识别
查看>>
HBase编程 API入门系列之delete(客户端而言)(3)
查看>>
Cocos2dx使用wxsqlite开源加密SQLite3数据库
查看>>
JMeter学习-内存溢出解决方法
查看>>
磨刀不误砍柴工——VS生成事件
查看>>
XE7 update1
查看>>
PHP RSA加解密示例(转)
查看>>
Mobile开发的饕餮盛宴-Zoomla!波CMS2 x2.1正式宣布
查看>>
swift:入门知识之控制流
查看>>
DICOM医学图像处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求
查看>>
Netstat 命令
查看>>
jQuery+HTML5弹出创意搜索框层
查看>>
应对Deadline,时间怎么安排?
查看>>
20140916阿里巴巴面试经历---成都站
查看>>