阅读 109

Spring源码解析系列四:Spring扫描组件之BeanFactoryPostProcessor

1.准备测试类

public class Test01 {
	public static void main(String[] args) {
		//这个构造方法会把Spring所有的环境都准备好
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
	}
}
复制代码

配置类

@ComponentScan("com.v1")
@Component
@Configuration
public class SpringConfiguration {

}
复制代码

PersonService类

@Component
public class PersonService {
}
复制代码

2.点击AnnotationConfigApplicationContext

	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		//这个类有父类,所以会先初始化父类的构造方法,接着初始化自己的构造方法
		//调用无参构造方法进行初始化一个读取器和扫描仪
		this();
		//把配置类加载进 DefaultListableBeanFactory 的map集合中
		//配置类可以一次性传多个,这个方法执行后,只是把配置类加载进了 DefaultListAbleBeanFactory的map集合中
		//还没有扫描其他的的加了组件的类
		register(annotatedClasses);
		//实例化所有被加了组件的对象
		refresh();
	}
复制代码

3.点击refresh()

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
			//这个方法不是重点,可以暂时认为他不干任何事情
			prepareRefresh();

			//获取工厂对象 ,本质是DefaultListableBeanFactory对象
			//其实读取xml文件变成beanDefinition,也是在这里面完成的
			//所以这里面的功能和register(annotatedClasses);功能很像
			//一个是是从xml文件中读取配置信息,一个是通过类的注解读取信息
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//为BeanFactory配置类加载器、后置处理器等等
			//这个方法比较重要
			prepareBeanFactory(beanFactory);

			try {
				//这个方法是空方法,Spring还没有做任何事情
				//猜测以后Spring会使用这个方法
				postProcessBeanFactory(beanFactory);


				//在这个方法中开始扫描被组件标记的类, 把类的信息
				// 封装成一个GenericBeanDefinition存储在map集合中
				//这个是非常重要的一个方法
				invokeBeanFactoryPostProcessors(beanFactory);
				
				//省略剩余代码...
				
				}
复制代码

4.点击 invokeBeanFactoryPostProcessors(beanFactory)

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

//重点方法,执行beanFactoryPostProcessors后置处理器
//注意这里 getBeanFactoryPostProcessors() 是获取不到用户自己的BeanFactoryPostProcessor的实现类的 ,因为这个时候还没有开始扫描包
//需要自己手动赋值给这个大容器对象,也就是AnnotationConfigApplicationContext
//ac.addBeanFactoryPostProcessor(....);
//getBeanFactoryPostProcessors()可以获取到用户自定义的作用类,前提是手动创建,传进来的	
    
 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}
复制代码

5.点击 invokeBeanFactoryPostProcessors

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// 1. 处理用户自己的后置处理器,处理的是用户自己创建对象传的ac.addBeanFactoryPostProcessor()
//如果你想在扫描所有包之前就执行你的后置处理器的话,可以首先把的后置处理器注册给Spring
//就是通过 ac.addBeanFactoryPostProcessor(对象) 这样子注解
		Set<String> processedBeans = new HashSet<>();
           //判断当前的beanFactory是否是BeanDefinitionRegistry
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//定义两个集合BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
//bdrpp 增强了一个功能 ,也就是说他们的功能是不一样的,所以需要定义两个集合
//regularPostProcessors 存储用户自己传进来的BeanFactoryPostProcessor的实现类
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//registryProcessors存储用户自己传进来的BeanDefinitionRegistryPostProcessor的实现类
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//判断的bean是否实现了BeanDefinitionRegistryPostProcessor
//如果bean实现了BeanDefinitionRegistryPostProcessor这个接口,可以获取到整个容器对象,也就是registry对象
//而实现BeanFactoryPostProcessor,只能获取 到bean工厂 对象
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					//如果当前的bean实现的是BeanDefinitionRegistryPostProcessor
					//添加进registryProcessors集合
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					//如果只是实现了beanFactoryPostProcessors添加进regularPostProcessors集合
					regularPostProcessors.add(postProcessor);
				}
			}
  //其实前面都不是重点,基本不会有人自己手动创建对象添加给Spring容器的,以下才是重点

//2.处理Spring内部的后置处理器,Spring内部的处理器 ,就只有一个类实现BeanDefinitionRegistryPostProcessor
//currentRegistryProcessors存放Spring内部类实现了BeanDefinitionRegistryPostProcessor接口的类
//ConfigurationClassPostProcessor 这个就是实现类 BeanDefinitionRegistryPostProcessor
//ConfigurationClassPostProcessor就是Spring内部的后置处理器
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

//从beanFactory工厂中寻找判断哪个类型实现了BeanDefinitionRegistryPostProcessor接口,拿出该类的beanName
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			//遍历所有的后置处理器beanName ,通过beanName从bean工厂中把对象取出来
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//把名称存储到processedBeans集合中
					processedBeans.add(ppName);
				}
			}
			//排序,不是重点 ,内部只有一个
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//合并list ,把用户之间定义和Spring之间内部的合并在一个集合中
            //合并基本是没有用的,一般用户不会自己手动创建对象注册进Spring容器
			registryProcessors.addAll(currentRegistryProcessors);

             //执行当前的后置处理器,其实到这里currentRegistryProcessors只有一个处理器,
			//主要处理扫描配置类对应包下的类
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清空集合
			currentRegistryProcessors.clear();
		  //剩余代码省略....其实下面的代码也有一部分很重要的,以后再聊
        
			}
复制代码

这个方法中主要干了哪些事呢?

遍历Spring容器的beanDefinitionMap集合查找哪个类实现了BeanDefinitionRegistryPostProcessor接口

注意,这个时候Spring容器中除了自己配置的一个SpringConfiguration类,还没有开始扫描任何自己定义的类进Spring容器

不了解 SpringConfiguration是什么时候被加载进Spring容器的,可以查看:

[Spring源码解析系列一:配置类的初始化过程] juejin.im/post/5d7b7b…

此时的Spring容器的beanDefinitionMap中,只有一个是我们定义的类 SpringConfiguration,其余的都是Spring内部定义的类

Spring内部定义的类其实就只有一个是实现了BeanDefinitionRegistryPostProcessor接口的,这个类就是

ConfigurationClassPostProcessor,这个类就是Spring中作为扫描组件的重要角色

6.在Idea中双击查询`ConfigurationClassPostProcessor

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
      PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware
复制代码

7.点击BeanDefinitionRegistryPostProcessor

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}
复制代码

8.点击 BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * 自己定义一个类,重写这个方法,可以获取到 bean工厂,插手bean的实例化过程
	 * 获取到bean工厂对象
	 *
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
复制代码

BeanFactoryPostProcessorBeanPostProcessor一样,也是Spring的扩展点之一

那这两者有什么区别呢?

BeanPostProcessor

public interface BeanPostProcessor {

	/**
	 * 在bean的初始化之前执行
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 在bean的初始化之后执行
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
复制代码
  • beanPostProcessor是bean级别的,是针对某个bean进行处理,beanPostProcessor的执行是在bean实例化的前后执行的

  • 实现 beanPostProcessor接口可以干扰bean的实例化过程

不理解 beanPostProcessor的作用,可以查看

[Spring的后置处理器到底是怎么回事?]juejin.im/post/5df066…

BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * 自己定义一个类,重写这个方法,可以获取到 bean工厂,插手bean的实例化过程
	 * 获取到bean工厂对象
	 *
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
复制代码
  • BeanFactoryPostProcessor是beanFactory级别的,是针对整个bean工厂的处理
  • BeanFactoryPostProcessor可以对整个工厂的 BeanDefinition进行干扰,甚至是自定义BeanDefinition注册给Spring容器

BeanFactoryPostProcessor的执行顺序优先于 BeanPostProcessor

BeanFactoryPostProcessor的执行是在类被描述成 BeanDefinition的之后,

BeanPostProcessor的执行是在bean被实例化的时候

9.我们回到 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor这个类其实就是一个处理这个Bean工厂的后置处理器

该类实现了BeanDefinitionRegistryPostProcessor,BeanDefinitionRegistryPostProcessor有继承了

BeanFactoryPostProcessor接口

ConfigurationClassPostProcessor这个处理器作用为:

读取配置类 SpringConfiguration的信息,从而扫描被加了 @Component的组件,封装为 BeanDefinition添加到Spring容器中

9.总结

本章主要讲了Spring扫描组件进Spring容器的一部分过程,在这个过程中,我们引出了后置处理器 BeanFactoryPostProcessor,比较了BeanFactoryPostProcessorbeanPostProcessor区别

下一章写:

ConfigurationClassPostProcessor到底是如何扫描组件组件进Spring容器的

视频讲解:

www.bilibili.com/video/av678…

视频为自己学习的时候录制的,也方便自己以后看

Spring5源码地址:

github.com/zouchangfu/… gitee.com/zouchangfu/…

Spring5源码都是已经构建好的了,无需再使用gradle进行构建了,直接打开就可以跑起来

写在最后:

大二学生一枚,挤时间写博客不容易,看完顺手点个赞,你的点赞是对我最大的鼓励

关注下面的标签,发现更多相似文章
评论