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 { } 复制代码
AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { //这个类有父类,所以会先初始化父类的构造方法,接着初始化自己的构造方法 //调用无参构造方法进行初始化一个读取器和扫描仪 this(); //把配置类加载进 DefaultListableBeanFactory 的map集合中 //配置类可以一次性传多个,这个方法执行后,只是把配置类加载进了 DefaultListAbleBeanFactory的map集合中 //还没有扫描其他的的加了组件的类 register(annotatedClasses); //实例化所有被加了组件的对象 refresh(); } 复制代码
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); //省略剩余代码... } 复制代码
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())); } } 复制代码
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中作为扫描组件的重要角色
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware 复制代码
BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; } 复制代码
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被实例化的时候
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor
这个类其实就是一个处理这个Bean工厂的后置处理器
该类实现了 BeanDefinitionRegistryPostProcessor
, BeanDefinitionRegistryPostProcessor
有继承了
BeanFactoryPostProcessor
接口
ConfigurationClassPostProcessor
这个处理器作用为:
读取配置类 SpringConfiguration
的信息,从而扫描被加了 @Component
的组件,封装为 BeanDefinition
添加到Spring容器中
本章主要讲了Spring扫描组件进Spring容器的一部分过程,在这个过程中,我们引出了后置处理器 BeanFactoryPostProcessor
,比较了 BeanFactoryPostProcessor
和 beanPostProcessor
区别
下一章写:
ConfigurationClassPostProcessor
到底是如何扫描组件组件进Spring容器的