在Sping的整个生命周期中,有9个地方调用后置处理器。这些后置处理器是spring实现自定义功能或者扩展spring的核心所在

一、实例化前

该方法属于InstantiationAwareBeanPostProcessor后置处理器

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}}

该方法的意思其实也体现到名字上了,就是在实例化之前做些什么。
如果该方法返回非空,代表整个创建流程提前结束,也就是说后面什么属性设置,bean的初始化等等都不会执行了,所以重写该方法一定要谨慎。这个方法一般会和 applyBeanPostProcessorsAfterInitialization后置结处理器结合使用,这个处理可是实现aop的核心,这个后面在分析。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}

因为如果你在applyBeanPostProcessorsBeforeInstantiation中返回非空后,后面spring的流程就不会走了,但是如果你有个切面是想代理这个类,那就没有办法了,所以applyBeanPostProcessorsBeforeInstantiation返回非空后会调用applyBeanPostProcessorsAfterInitialization执行aop代理

至于网上说的说法:

如果这里出现了aop的切面类,就会有InstantiationAwareBeanPostProcessor的子处理器进行类的过滤,出现@AspectJ的类标记为不需要代理的类,会被放入map中

我目前不理解,我自己写了一个切面类,结果还是和正常类走相同的流程。

二、实例bean前决定构造器

createBeanInstance中的方法determineConstructorsFromBeanPostProcessors中会调用SmartInstantiationAwareBeanPostProcessor 后置处理器的determineCandidateConstructors方法。

2.1 SmartInstantiationAwareBeanPostProcessor


该构造器主要就是为了预测最终bean的类型(predicting the eventual type of a processed bean)。

2.2 determineCandidateConstructors

该方法也是此处构造器的真正要做的事情。就是为了决定实例化bean的构造器

private DeptService service;public DeptController(@Autowired DeptService service){this.service = service;
}

比如这种情况,肯定不走默认的构造函数,spring就会在determineCandidateConstructors中决定出这个有参数的构造器,然后创建实例的时候回检查参数是否有@Autowired的,在构造的时候就会把service给创建好

三、刚创建好实例之后

createBeanInstance之后,这个时候bean的属性、初始化方法等等都没有创建好,基本属于空白对象。然后在方法applyMergedBeanDefinitionPostProcessors中执行类MergedBeanDefinitionPostProcessor的后置处理

3.1 MergedBeanDefinitionPostProcessor


这个类主要用来更改或者丰富bean的定义的元数据信息。

3.2 方法postProcessMergedBeanDefinition

  1. CommonAnnotationBeanPostProcessor:这个是MergedBeanDefinitionPostProcessor 一个重要的子类,在这个类中
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);//主要记录生命周期方法InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);//记录@Resource  metadatametadata.checkConfigMembers(beanDefinition);}

可见主要是为了后面的流程进行的一些辅助动作。

  1. AutowiredAnnotationBeanPostProcessor:另外一个重要的子类。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);//记录@AutoWired medatametadata.checkConfigMembers(beanDefinition);}

还是为了后面的流程进行的一些辅助动作。

四、解决循环依赖

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}

上面这段源码是在创建好bean后,如果开启了循环依赖,那么会执行

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

这个时候就来到了主角 getEarlyBeanReference这里。

可见该后置处理器属于SmartInstantiationAwareBeanPostProcessor,这里到底是做什么呢?

4.1 AbstractAutoProxyCreator

改具体子类实现了SmartInstantiationAwareBeanPostProcessor接口。

public Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return wrapIfNecessary(bean, beanName, cacheKey);}

这个代码就是返回aop代码的代码。 所以该后置处理器有个功能就是返回aop的代理

五、实例化后

在属性填充方法populateBean

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}

改后置处理器来自InstantiationAwareBeanPostProcessor,调用其中的postProcessAfterInstantiation
改方法功能也简单,就是判断是否进行属性注入。

六 设置属性前

for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}

改后置处理器用在 在工厂将给定的属性值应用到给定bean之前,对给定的属性值进行后处理。你可以进行一些检查,比如某个属性是 “required”的,但是这个属性需要的引用却是空,这个时候可以进行一些检查工作。还有dubbo的注解 @DubboReference这个注解,就是在此处 替换需要注入的类来实现的。

七 执行初始化方法前

if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}

改代码是在方法initializeBean中调用的。applyBeanPostProcessorsBeforeInitialization详细调用是

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

可以看到他的引用是接口BeanPostProcessor这个接口属于顶级接口,他的子类太多了,其中有个出名的是CommonAnnotationBeanPostProcessor 该类的结构图是

其中他的父类InitDestroyAnnotationBeanPostProcessor是个重点角色,在改类中的postProcessBeforeInitialization方法中就执行了大名鼎鼎的 @PostConstruct 注解的方法。

八 执行初始化方法后

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

鼎鼎大名的aop就是在这里进行实现的。具体的后置处理器是AbstractAutoProxyCreator

九 销毁bean容器的时候调用

具体后置处理器InitDestroyAnnotationBeanPostProcessor

然后调用的方法是postProcessBeforeDestruction

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {metadata.invokeDestroyMethods(bean, beanName);}catch (InvocationTargetException ex) {String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";if (logger.isDebugEnabled()) {logger.warn(msg, ex.getTargetException());}else {logger.warn(msg + ": " + ex.getTargetException());}}catch (Throwable ex) {logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);}}

什么是destory方法呢,被javax.annotation.PreDestroy 注解的的方法。

Spring的9处调用后置处理器相关推荐

  1. 2.5、调用后置处理器

    在idea中搜索了一下Spring的后置处理器(PostProcessor),找出了下图的几个 本文主要来分析红框中标出的两个,也就是在 refresh() 方法的第5步调用的后置处理器 1.后置处理 ...

  2. 攀登Spring珠穆朗玛峰:前置与后置处理器

    文章目录 Spring的前置与后置处理器 前提知识 前置与后置处理器定义 前置处理器:BeanFactoryPostProcessor `postProcessBeanFactory`调用 后置处理器 ...

  3. Spring 详解Bean的后置处理器

    Bean的后置处理器详解: Spring当中的后置处理器是Spring体用的一个扩展点,开发者只要去实现,Spring当中的BeanPostProcessor接口,那么就能插手SpringBean实例 ...

  4. spring的后置处理器(未完结版)

    学习spring源码也有一阶段时间了,是时候收货的季节了,打算写几篇博客,把自己的知识沉淀下来.在学习spring的源码之前,别人问我spring什么牛逼.我会毫不犹豫的说出AOP,IOC啊.但是看看 ...

  5. Spring中Bean的后置处理器

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html: Bean后置处理器 BeanPostProce ...

  6. spring源码:九大后置处理器

    目的: spring在完成一个bean的初始化.实例化的过程中,会用到九个后置处理器:本文梳理出这九个后置处理器 九大后置处理器 spring在初始化的过程中,会在九个地方分别调用了五个后置处理的九个 ...

  7. Spring之BeanPostProcessor(后置处理器)介绍

      为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口 BeanPostProcessor   该接口我们也叫后置处理器,作用是在Be ...

  8. spring--bean后置处理器(BeanPostProcessor)原理解析

    文章目录 功能描述: 如何使用: 定义要处理的接口类型 添加实际需要处理的类 定义后置处理器 编写测试类 执行日志 后置处理器加载解析 registerBeanPostProcessors注册拦截be ...

  9. Spring容器创建流程(4)调用beanFactory后置处理器

    postProcessBeanFactory() 方法留给子类去实现. invokeBeanFactoryPostProcessors() 调用bean工厂的后置处理器(以前的执行流程可在系列文章中查 ...

最新文章

  1. 2021年大数据常用语言Scala(三):Scala解释器
  2. html标题标签最大值是多少,css – 样式HTML5进度标记,达到了它的最大值
  3. PHP利用Curl、socket、file_get_contents POST数据
  4. linux用户双重认证登录,linux PAM 用户登录认证
  5. thinkphp mysql函数_thinkphp对数据库操作有哪些内置函数
  6. Parallels 发布 Desktop 17版本,支持 Windows 11 和 macOS Monterey
  7. 云评测 | OpenStack智能运维解决方案 @文末有福利!
  8. MySQL中 Data truncated for column ‘xxx‘解决方法
  9. iOS分析友盟错误报告
  10. UNIX系统基本结构
  11. 2020年高压电工考试APP及高压电工模拟考试软件
  12. 转android gralloc流程分析for msm8960
  13. 域名注册之后如何操作
  14. 企业上云,打造数字经济新动能
  15. 基于腾讯云的多人视频会议的在线语音转写功能的实现
  16. Office2019 卸载重新安装-2022 Win10【不花钱+官方途径】
  17. 中国移动清退3G进行时
  18. Java停止线程的3种方式
  19. Sage X3基于业务的预算管理
  20. Java Api 操作 Hbase

热门文章

  1. Adv-Makeup:一种新颖不易察觉且可迁移的人脸识别攻击方法
  2. html图片标签img的介绍以及基本用法详解
  3. 实现从淘宝(天猫)定时抓取订单数据、打印电子面单并保存到ERP表中
  4. 【数据分析】2022 年将占据主导地位的 3 种数据和分析趋势
  5. 《算法基础》线性枚举(一)——最值算法
  6. python从0到1_从0到1的Python学习经验
  7. 内存条 udimm rdimm 等和 ECC 功能
  8. Delphi TreeView树型框节点拖拽停靠、按条件开始拖拽
  9. 计算机专业去空军地勤能干嘛,空军地勤退役后能干什么?
  10. (一)TileMap使用