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;
}
复制代码
BeanFactoryPostProcessor
和BeanPostProcessor
一样,也是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
,比较了BeanFactoryPostProcessor
和beanPostProcessor
区别
下一章写:
ConfigurationClassPostProcessor
到底是如何扫描组件组件进Spring容器的
视频讲解:
视频为自己学习的时候录制的,也方便自己以后看
Spring5源码地址:
github.com/zouchangfu/… gitee.com/zouchangfu/…
Spring5源码都是已经构建好的了,无需再使用gradle进行构建了,直接打开就可以跑起来