Spring提供开放式接口整理系列一

本文详细解析了Spring中的BeanPostProcessor接口,介绍了其在Bean初始化过程中的应用,包括调用时机、源码分析以及相关疑问的解答。通过分析,揭示了BeanPostProcessor在配置类初始化完成后,对其他bean进行回调的原因和实现机制,并探讨了AOP在回调方法中的实际应用场景。
摘要由CSDN通过智能技术生成

Spring源码分析之BeanPostProcessor

Bean定义后置处理器(一)–BeanPostProcessor

1.、 应用场景 ,Bean定义在初始化的时候,我们可以偷偷的做一些事情,比如修改bean的一些信息等;
Spring组件在创建的时候,都会方法回调,既能获取这个组件而且我们可以做一些初始化数据的工作。
2、 源码分析

// BeanPostProcessor 接口如下
public interface BeanPostProcessor {
   
//第一个接口
postProcessBeforeInitialization(Object bean, String beanName)//第二个接口
postProcessAfterInitialization(Object bean, String beanName)}

截图:
在这里插入图片描述
发现该接口被重写,那意味着不同的场景,子类有自己的实现逻辑,如下大量的子类继承这个接口,肯定重写以上两个方法。
在这里插入图片描述

2、 调用时机
对于调用时机来说,也是我们学习Spring最大的收获,因为知道了调用时机,我们可以很好的利用这个时机,完成我们特定的业务需求,即场景的实现。分析这块,不妨先从Spring IOC源码进行解读。
首先看一段代码:

@Component
public class MyFactoryBean implements BeanPostProcessor {
   

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   
      System.out.println("postProcessBeforeInitialization"+"方法执行了,BeanName为:"+beanName);
      return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   
      System.out.println("postProcessAfterInitialization"+"方法执行了,beanName为:"+beanName);
      return bean;
  }
}

配置类如下,扫描是可以扫描到上面的Bean组件

@Configuration
@ComponentScan("com.xxsc.cn.testf")
public class MyConfig {
   
}

运行代码

public class AppTest {
   

    public static void main(String[] args) {
   
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    }
}

打印结果:

postProcessBeforeInitialization方法执行了,BeanName为:myConfig
postProcessAfterInitialization方法执行了,beanName为:myConfig

那么可以断定,在Spring容器启动的时候,上面这两个方法执行了,根据BeanName的名字,进一步可断定Spring IOC在创建myConfig组件的时候,触发的,myConfig组件确实我们的配置类。
接下来,需要在关键节点打断点,先根据代码运行情况,分析在何时进行回调。
断点一:

AbstractApplicationContext 类 的 invokeBeanFactoryPostProcessors(beanFactory);方法,这个方法大概解释一下:Spring进行bean定义,并把Bean定义加载到容器当中,(bean定义是对Bean的描述,此时的bean没有初始化,更没有赋值)

断点二:

AbstractAutowireCapableBeanFactory 类的 doCreateBean方法的instanceWrapper = createBeanInstance(beanName, mbd, args);这一行
对于这一行的代码,在这之前,扫描完成的bean定义集合进行遍历,对bean定义进行初始化,也就是通过反射的技术创建对象,对于之前的分析,此时我们关注的应该是beanName为myConfig,断点条件设置为beanName.equals("myConfig")

断点三:

AbstractAutowireCapableBeanFactory 类的 doCreateBean方法的populateBean(beanName, mbd, instanceWrapper);这一行
对于这一行的代码,是对bean进行赋值,简单理解:断点二处,为new的操作(默认构造函数,如果是有参构造,此时断点二就开始赋值了),new完对象,断点三进行set赋值操作,因为spring依赖的属性,在创建bean的时候,就已经赋值,也就是DI注入了。此时对于断点同样设置条件:beanName.equals("myConfig")

断点四:

紧接着断点三的下一行代码,exposedObject = initializeBean(beanName, exposedObject, mbd);这行代码可以很NB了,spring提供了大量的开放式接口,用于我们去重写使用,对于这行代码,赋值完成之后,spring提供开放式接口,可以对bean一些修改,或者是获取spring中关系的信息,后面会写到。

DUBUG运行:
在这里插入图片描述
断点一并没有触发,断点二对bean进行初始化,发现也是没有回调。
断点三对于bean赋值完成之后,发现还是没有回调。
在这里插入图片描述
走完断点三,发现回调了,那么此时,执行时机来了: 配置类在初始化完成并且对配置类完成赋值之后,对于实现BeanPostProcessor的bean进行回调,那么对不对呢,需要来分析一下initializeBean这个方法到底做了写什么事,为什么会在这个地方进行方法的回调。
在这里插入图片描述
Debug进入到initializeBean方法的if (mbd == null || !mbd.isSynthetic()) { 这行代码,
在这里插入图片描述
再次进入到applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);这行代码
在这里插入图片描述
有个for循环,猜测找出BeanPostProcessor类型的子类,进行方法回调。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值