【Spring源码】7.如何添加自定义的BeanFactoryPostProcessor
持续创作,加速成长!这是我参与「掘金日新计划 · 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