【Spring源码】7.如何添加自定义的BeanFactoryPostProcessor

语言: CN / TW / HK

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

放在前面的一段亲子鉴定...

关于BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcesso两人的关系声明—— 由下图可以看出BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,属父子关系

还可以查看下族谱(类继承关系)

步骤:

  • 打开想要查看的类
  • 空白处右键
  • 注意⚠️右键的焦点要落在类的大括号里面(不然只会出现查看依赖的选项)
  • Diagrams->Show Diagram

  • 显示结果

实属父(BeanFactoryPostProcessor)子(BeanDefinitionRegistryPostProcessor)关系,鉴定完毕!

保姆级正文开始

1. 新建类

新建两个类,分别实现BeanFactoryPostProcessor接口和BeanDefinitionRegistryPostProcessor接口(任选一个也可以,本文为了介绍全面,两个同时举例🌰)

MyBeanFactoryPostProcessor.java(实现BeanFactoryPostProcessor接口)

```java package com.aqin.custom.postprocessor;

import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

/* * @author aqin1012 AQin. * @date 2022/6/7 3:23 PM * @Version 1.0 / public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("俺这是MyBeanFactoryPostProcessor.postProcessBeanFactory()W(0)W~"); } } ```

MyBeanDefinitionRegistryPostProcessor.java(实现BeanDefinitionRegistryPostProcessor接口)

```java package com.aqin.custom.postprocessor;

import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

/* * @author aqin1012 AQin. * @date 2022/6/6 11:05 AM * @Version 1.0 / public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("俺这是MyRegistryPostProcessor.postProcessBeanFactory()( ´▽`)~"); }

@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("俺这是MyRegistryPostProcessor.postProcessBeanDefinitionRegistry()(*≧ω≦)~"); } } ```

2. 让Spring识别

方式主要有2种:

方式一:在配置文件中添加定义(让spring自动识别)

启动类:AqinApplication.java

配置文件:applicationContext2.xml

```xml

```

测试查看输出结果:

方式二:重写customizeBeanFactory函数(用户手动添加)

新建ClassPathXmlApplicationContext的继承类

MyApplicationContext.java

```java package com.aqin.custom.postprocessor;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/* * @author aqin1012 AQin. * @date 2022/6/6 11:14 AM * @Version 1.0 / public class MyApplicationContext extends ClassPathXmlApplicationContext {

public MyApplicationContext(String... s) { super(s); } } ```

修改启动类

```java package com.aqin;

import com.aqin.custom.postprocessor.MyApplicationContext; import org.springframework.context.ApplicationContext;

import java.util.Arrays;

/* * @author aqin1012 AQin. * @date 2022/4/24 5:44 PM * @Version 1.0 / public class AqinApplication { public static void main(String[] args) { ApplicationContext context = new MyApplicationContext("applicationContext2.xml"); System.out.println(Arrays.toString(context.getBeanDefinitionNames())); } } ```

重写customizeBeanFactory函数

```java package com.aqin.custom.postprocessor;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext;

/* * @author aqin1012 AQin. * @date 2022/6/6 11:14 AM * @Version 1.0 / public class MyApplicationContext extends ClassPathXmlApplicationContext {

public MyApplicationContext(String... s) { super(s); }

@Override protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { super.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor()); super.addBeanFactoryPostProcessor(new MyBeanDefinitionRegistryPostProcessor()); } } ```

测试查看输出结果:

BBBBBBBBut、这两种方法有一点区别

来吧~总结下,不知道有没有同学注意到,我在启动类里都有一行输出

System.out.println(Arrays.toString(context.getBeanDefinitionNames()));

其实就是spring上下文中的一个集合对象BeanDefinitionNames的输出,先啰嗦解释下BeanDefinitionNames这个集合(了解的同学可以直接跳过下面这段,或者瞅瞅哪里解释的不对评论区戳我~~)

spring在读取Bean后,会先将其转化成BeanDefinition(Bean定义),存入到BeanDefinitionMap和BeanDefinitionNames这两个集合中:

  • 其中BeanDefinitionMap是一个Map,key值存放字符串格式的BeanName(Bean的名称),value值存放BeanDefinition格式的Bean定义
  • BeanDefinitionNames是一个List,里面只存放了这些Bean的名称

拿DefaultListableBeanFactory举个例子🌰,如下图,这两个集合在类DefaultListableBeanFactory中的定义:

然后我们分别查看两种方式的输出->

虽然两种让spring发现方式新建类中的输出都被执行了,但是可以看到通过重写customizeBeanFactory函数进行扩展的spring上下文对象中的BeanDefinitionNames和BeanDefinitionMap都是空的,而通过配置文件让spring识别的则将我们在第一步新建的两个PostProcesscor都加了进去。

我们在通过Debug的方式仔细看下->

方式一:

方式二:

总之~

就是后面那种我们在第一步新建的两个类虽然也都会执行,但是第二种方法是不会被当成spring的bean添加进BeanDefinitionMap和BeanDefinitionNames这两个集合中,这是两种方式的主要区别。

欢迎发现问题的同学(大佬)指教>>>(=゚ω゚)ノ抱拳.gif