文章目录

  • Pre
  • org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
  • InstantiationAwareBeanPostProcessor 注册过程源码分析
    • postProcessBeforeInstantiation的执行时机源码解析
  • 使用场景 : 创建代理类


Pre

Spring Boot - 扩展接口一览


org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

注意下: Initialization 表示 初始化 (意思是对象已经生成) 。 Instantiation 表示 实例化 (意思是对象还未生成) 。

接口继承了BeanPostProcess接口 , 从方法上我们也可以看出 InstantiationAwareBeanPostProcessor 做了一些扩展 。

BeanPostProcess接口只在bean的初始化阶段进行扩展(注入spring上下文前后),而InstantiationAwareBeanPostProcessor接口在此基础上增加了3个方法,使得扩展接口可以在实例化阶段和属性注入阶段

该类主要的扩展点有以下5个方法,主要在bean生命周期的两大阶段:实例化阶段 和初始化阶段

(1)实例化: 实例化的过程是一个创建Bean的过程,即调用Bean构造函数,单例的Bean入单例池中

(2)初始化: 初始化的过程是一个赋值的过程,即调用Bean的setter方法,设置Bean属性

InstantiationAwareBeanPostProcessor作用于过程(1)实例化前后; BeanPostProcessor用于过程(2)初始化前后


按调用顺序,我们来看一下

  • postProcessBeforeInstantiation:实例化bean之前,相当于new这个bean之前
  • postProcessAfterInstantiation:实例化bean之后,相当于new这个bean之后
  • postProcessPropertyValues: bean已经实例化完成,在属性注入时阶段触发, @Autowired,@Resource等注解原理基于此方法实现
  • postProcessBeforeInitialization:初始化bean之前,相当于把bean注入spring上下文之前
  • postProcessAfterInitialization:初始化bean之后,相当于把bean注入spring上下文之后

InstantiationAwareBeanPostProcessor 注册过程源码分析

我们还是从

org.springframework.context.support.AbstractApplicationContext#refresh

开始看 ,主要是下面两个方法

.......
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);.......// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

看下调用栈

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);org.springframework.beans.factory.support.AbstractBeanFactory#getBeanorg.springframework.beans.factory.support.AbstractBeanFactory#doGetBean  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

createBean跟进去

@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}//省略....Object beanInstance = doCreateBean(beanName, mbdToUse, args);return beanInstance;}

通过上面的代码,我们可以看到在执行doCreateBean之前有resolveBeforelnstantiation方法; 看注释

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  • resolveBeforelnstantiation判断执行InstantiationAwareBeanPostProcessor.postProcessBeforelInstantiationg接口方法实现;
  • doCreateBean创建bean方法;

postProcessBeforeInstantiation的执行时机源码解析

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);org.springframework.beans.factory.support.AbstractBeanFactory#getBeanorg.springframework.beans.factory.support.AbstractBeanFactory#doGetBean  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

重点看 resolveBeforeInstantiation

 /*** Apply before-instantiation post-processors, resolving whether there is a* before-instantiation shortcut for the specified bean.* @param beanName the name of the bean* @param mbd the bean definition for the bean* @return the shortcut-determined bean instance, or {@code null} if none*/@Nullableprotected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;//如果beforeInstantiationResolved还没有设置或者是false(说明还没有需要在实例化前执行的操作)if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.// 判断是否有注册过InstantiationAwareBeanPostProcessor类型的beanif (!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

 /*** Apply InstantiationAwareBeanPostProcessors to the specified bean definition* (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.* <p>Any returned object will be used as the bean instead of actually instantiating* the target bean. A {@code null} return value from the post-processor will* result in the target bean being instantiated.* @param beanClass the class of the bean to be instantiated* @param beanName the name of the bean* @return the bean object to use instead of a default instance of the target bean, or {@code null}* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation*/@Nullableprotected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {// 循环处理for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);//只要有一个result不为null;后面的所有 后置处理器的方法就不执行了,直接返回(所以执行顺序很重要)if (result != null) {return result;}}return null;}

当然了也有 postProcessAfterInitialization

 @Overridepublic 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;}

使用场景 : 创建代理类

 package com.artisan.bootspringextend.testextends;import com.artisan.bootspringextend.service.ArtisanServiceImpl;
import com.artisan.bootspringextend.service.ClassA;
import com.artisan.bootspringextend.service.ClassAInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.context.annotation.Configuration;/*** @author 小工匠* @version 1.0* @description:* @date 2022/11/28 0:33* @mark: show me the code , change the world*/@Slf4j
@Configuration
public class ExtendInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {private static final String VALUE = "classA";@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (VALUE.equals(beanName)) {log.info("4  beanName {}-----> postProcessBeforeInitialization", beanName);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (VALUE.equals(beanName)) {log.info("5   beanName {}-----> postProcessAfterInitialization", beanName);}return bean;}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanClass == ClassA.class) {log.info("1  beanName {} -----> postProcessBeforeInstantiation", beanName);Enhancer enhancer = new Enhancer();enhancer.setSuperclass(beanClass);enhancer.setCallback(new ClassAInterceptor());ClassA classA = (ClassA) enhancer.create();log.info("proxy created ---->{}", classA.toString());return classA;}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (VALUE.equals(beanName)) {log.info("2   beanName {}-----> postProcessAfterInstantiation", beanName);}return false;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if (VALUE.equals(beanName)) {log.info("3   beanName {} -----> postProcessProperties", beanName);}return pvs;}
}

我们可以看到 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 生成了代理类后,直接执行了 初始化后的动作 BeanPostProcessor#postProcessAfterInitialization

Spring - InstantiationAwareBeanPostProcessor 扩展接口相关推荐

  1. Spring8:一些常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  2. java 扩展接口_详解常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  3. Spring - BeanFactoryPostProcessor 扩展接口

    文章目录 Pre org.springframework.beans.factory.config.BeanFactoryPostProcessor 源码探究 1 是否实现BeanDefinition ...

  4. Spring - DisposableBean扩展接口

    文章目录 Pre org.springframework.beans.factory.DisposableBean 使用场景 源码解析 扩展示例 Pre Spring Boot - 扩展接口一览 or ...

  5. Spring - ApplicationContextInitializer 扩展接口

    文章目录 Pre org.springframework.context.ApplicationContextInitializer扩展点 扩展接口 扩展生效方式 方式一 : Spring SPI扩展 ...

  6. Spring - BeanDefinitionRegistryPostProcessor 扩展接口 动态注册bean

    文章目录 Pre org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor 接口的继承关系 BeanD ...

  7. Spring Boot - 扩展接口一览

    文章目录 扩展接口 扩展接口

  8. SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)

    微信公众号:吉姆餐厅ak 学习更多源码知识,欢迎关注. SpringBoot2 | SpringBoot启动流程源码分析(一) SpringBoot2 | SpringBoot启动流程源码分析(二) ...

  9. 动态管理配置文件扩展接口EnvironmentPostProcessor

    SpringBoot支持动态的读取文件,留下的扩展接口org.springframework.boot.env.EnvironmentPostProcessor.这个接口是spring包下的,使用这个 ...

最新文章

  1. POST和GET有什么区别? [重复]
  2. 算法提高课-动态规划-树形DP-AcWing 1072. 树的最长路径:dfs写法
  3. 【渝粤教育】电大中专电子商务网站建设与维护 (9)作业 题库
  4. android游戏黑屏,第五人格游戏进不去黑屏解决办法
  5. QingStor分布式存储全线升级:自研需要勇气,成功还要看实力
  6. 为什么前端工程师的工作很难找?
  7. .NET Mail : 注意Win 7 不再包含SMTP服务
  8. sakai 工具翻译——测试和测验1
  9. 升流式水解酸化反应器设计计算_《HJ 2047-2015 水解酸化反应器污水处理工程技术规范》.pdf...
  10. 编码消耗率CCR,“上帝代码”,反射,简洁代码
  11. 深恶痛绝……残忍虐杀何时终止?
  12. 【深度解局】佛慢你:张小龙的微信成功三字诀
  13. Redis从入门到精通
  14. AFM技术原理及相关测试模式
  15. 系统集成项目管理工程师10大管理47个过程域输入输出工具(项目整体管理)
  16. 【40-系统性能压力测试基本概念-相关性能指标HPSTPSQPSRT-安装Jmeter教程-JMeter测试流程-线程组-取样器-监视器-测试商城首页-JMeter Address 占用的问题】
  17. 如何删除Windows更新后残留的文件
  18. NLP入门(五)用深度学习实现命名实体识别(NER)
  19. 智能制造业也开始进军元宇宙?
  20. win7安装IIS 防火墙设置

热门文章

  1. 字符串算法之KMP(字符串匹配)
  2. 1-初识DXGI与D3D
  3. CDH 6.3.2 安装(一)
  4. html背景图片 纵向拉伸,背景图片拉伸(CSS方法)_html/css_WEB-ITnose
  5. 15-top命令详解
  6. 网络爬虫(python项目)
  7. 从零开始学架构——异地多活架构
  8. 数字标牌行业嵌入式主板方案
  9. 一些实用的cmd命令,让你变得很牛X
  10. 蓝桥杯 算法训练 Tennis Rackets (50%通过)