【保姆级·创建对象】如何利用resolveBeforeInstantiation()在预处理阶段返回一个Bean的实例对象
创始人
2024-01-21 12:17:45

前情回顾

之前有篇文章我们有详细介绍了prepareMethodOverrides()方法并详细例举了一个lookup-method标签的例子

【保姆级】lookup-method标签实践与分析_AQin1012的博客-CSDN博客

本文我们来盘盘prepareMethodOverrides()方法后面的resolveBeaforeInstantiation()的函数,看过之前文章介绍的同学应该有印象,它是应用实例化前的前置处理器,是在正式实例化前的一种预处理方式(即在预处理阶段给BeanPostProcessors们一个机会来返回代理来代替真正的实例)

那么这个功能如何来实现呢?

本文我们就来仔细走一遍٩(˃̶͈̀௰˂̶͈́)و、

在createBean()方法中找到resolveBeforeInstantiation()

​仔细查看代码逻辑,发现如果我们想要确认beanClass是在此处进行处理的,则需要进入下图中判断逻辑,即需要同时满足2个条件:

  1. !mbd.isSynthetic()为true
  2. hasInstantiationAwareBeanPostProcessors()为true

isSynthetic()是判断当前mbd是否是合成的

  • “合成的”是指应用程序本身定义(不是用户定义,只有在实现AOP的时候Synthetic的值才是true)

hasInstantiationAwareBeanPostProcessor()是判断是否有任何InstantiationAwareBeanPostProcessors被注册叻

​这是一个标识符,表示是否有任何InstantiationAwareBeanPostProcessors被注册

所以如果我们想要进入if的逻辑中,就需要同时满足这两个条件,直接用Spring源码debug是不会进入的,所以我们需要创造条件,让程序进入if的逻辑中

首先,我们先看下InstantiationAwareBeanPostProcessor是什么~

​由上图可以看出InstantiationAwareBeanPostProcessor是BeanPostProcessor的一个实现接口

测试流程

创建一个简单类

BeanInstantiation.java

public class BeanInstantiation {public void smile() {System.out.println("♪───O(≧∇≦)O────♪");}
}

创建拦截器

MyMethodInterceptor.java

public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)throws Throwable {System.out.println("MyMethodInterceptor.interceptor(): " + method + "--->");/** 这里会调用具体的类的方法 */Object invokeSuper = methodProxy.invokeSuper(o, objects);System.out.println("<---MyMethodInterceptor.interceptor(): " + method);return invokeSuper;}
}

实现InstantiationAwareBeanPostProcessor

MyInstantiationAwareBeanPostProcessor.java

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {/** 创建代理 */if (beanClass == BeanInstantiation.class) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(beanClass);enhancer.setCallback(new MyMethodInterceptor());BeanInstantiation beanInstantiation = (BeanInstantiation) enhancer.create();System.out.println("创建代理对象:" + beanInstantiation);return beanInstantiation;}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println("=== postProcessAfterInstantiation ===");return false;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("=== postProcessBeforeInitialization ===");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("=== postProcessAfterInitialization ===");return bean;}/*** 对当前属性值的相关处理工作** @param pvs      the property values that the factory is about to apply (never {@code null})* @param bean     the bean instance created, but whose properties have not yet been set* @param beanName the name of the bean* @return* @throws BeansException*/@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println("=== postProcessProperties ===");return pvs;}
}

上面postProcessBeforeInstantiation()中的代码的作用是手动创建了一个代理对象(后面会出一篇动态代理的详解)

配置文件


测试类

public class test {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");BeanInstantiation beanInstantiation = (BeanInstantiation) applicationContext.getBean("beanInstantiation");beanInstantiation.smile();}
}

测试结果

添加特定的监测值

我们主要监测下hasInstantiationAwareBeanPostProcessors()是否为true,所以可以将hasInstantiationAwareBeanPostProcessors()添加为监测值(知道如何添加的同学可跳过再下面👇这部分)

1.点击+

2.在出现的空白条(下图中的红框框处)填入需要监测的变量

​3.回车确认添加

​Debug分析

在这个判断语句处打个断点,如下图箭头指向位置

在测试类中使用debug模式启动程序,执行至断点处可以看到,由于我们的配置文件中配置了两个Bean,而此时加载的Bean是myInstantiationAwareBeanPostProcessor,故当前的hasInstantiationAwareBeanPostProcessors()=false

所以继续下一步的时候也不会进入判断内的逻辑

​我们点击左侧的绿色箭头直接进入下一个断点

​再次进入我们刚刚停留的位置

​而此时加载的Bean是beanInstantiation,故当前的hasInstantiationAwareBeanPostProcessors()=true,继续下一步

一步一步执行下去,最后返回Bean的代理类

搞定~(。・ω・。)ノ🎉~~

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
1和0什么意思网络用语 0和1... 最近,有网友给大家出了份考卷,卷面是几位“00后”的QQ对 话:dbq、xswl、nss、nbcs、...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
七大洲八大洋 七大洲简易图三角... 一、北美洲(中北美和加勒比海)北美洲面积约2471万平方公里,居世界第三。人口约5.79亿(2016...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...