概述
本文地址https://blog.csdn.net/hancoder/article/details/111413351
说明,本文参考了子路老师博客https://blog.csdn.net/java_lyvee/category_7351027.html,但自己也看过很多这方面的视频,包括尚硅谷的注解驱动开发,所以加了些自己的说明,尽量简洁。个人认为此文是我近期写的最好的一篇了,我感觉快要打通ssm源码整合了。
按理说工厂后置处理器没有getBean重点,但是我读了那么久源码迟迟有些地方不懂,就是因为当初没有读好工厂的后置处理器,一直没有搞懂注解的注册时机,再加上尚硅谷讲的@EnableAspectJAutoProxy
也没说好到底怎么个注册法,看了几遍才发现是工厂后置处理器的问题。故写了此文
正在更新spring源码系统文章:
一、工厂后置处理器基础知识
工厂后置处理器的作用是新增和修改bean定义的,而spring中有两个接口
与工厂后置处理器有关,分别是BeanFactoryPostProcessor
、BeanDefinitionRegistryPostProcessor
。
- BeanFactoryPostProcessor:需要实现一个方法。只能修改bean定义
- BeanDefinitionRegistryPostProcessor:他本身有一个需要实现方法,但因为继承了上面的BeanFactoryPostProcessor接口,所以需要实现2个方法。分别是修改和添加bean定义
在实际开发中用的比较少,但各个框架源码整合中用的比较多,这里我们就不写用法了,直接看helloworld吧。
二、测试代码
bean定义:bean Definition,我们简称bd,存放bd的map我们简写为bd map,不懂bd的可以取前文看
1 工厂后置处理器
我们首先需要了解他们的用法,如下,我分别为每个接口创建了个实现类,只做了简单打印,用来看看他当时里面有什么bean定义,并用注解@Component将他们加到spring容器中。
1.1 注解的:
这里是意思是定义BeanFactoryPostProcessor的实现类,并且在上面@Component。然后在里面的postProcessBeanFactory()方法里打印当前有多少个bd
@Component
public class MyFacPostProcess_zhujie // 后面有_zhujie的标识
implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===注解的MyFacPostProcess.postProcessBeanFactory()被执行。。。");
int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
}
}
和上面的逻辑一样,定义BeanDefinitionRegistryPostProcessor的实现类,并@Component。他们都是后置处理器,只不过BeanDefinitionRegistryPostProcessor可以新增和修改bd,而上面的BeanFactoryPostProcessor只能修改bd。
所以我们在它的新增bd方法里尝试new bd并设置class,然后用registry注册器注册到容器中
@Component
public class MyBeanDefinitionRegistryPostProcessor_zhujie
implements BeanDefinitionRegistryPostProcessor {
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("===注解的MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()执行。。。");
int count = registry.getBeanDefinitionCount();//bean定义的数量
String[] names = registry.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
// 新增bd
GenericBeanDefinition genericBeanDefinition =
new GenericBeanDefinition() ;
genericBeanDefinition.setBeanClass(Yellow.class);
registry.registerBeanDefinition("yellow1",genericBeanDefinition);
}
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===注解的MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()执行。。。");
int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
}
}
1.2 通过ac.addBeanFactoryPostProcessor添加的实体bean
这里的意思是我们又定义了上面两个接口的实现类,只不过没加@Component,一会再手动注册
注意不要加@Component注解,我们要手动注册工厂后置处理器。而且我们传入ac的时候已经是实例化好的
public class RuCanBeanDefinitionRegistryPostProcessor // rucan的意思是说一会要手动注册
implements BeanDefinitionRegistryPostProcessor {
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("===入参的registry.postProcessBeanDefinitionRegistry()执行。。。");
}
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===入参的registry.postProcessBeanDefinitionRegistry()执行。。。");
}
}
public class RuCanBeanFactoryPostProcessor
implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===入参的普通factoryPostPro.postProcessBeanDefinitionRegistry()执行。。。");
}
}
1.3 通过ac.registerBeanDefinition添加的bd
(下面这两个类不用太在意,其实是我前期没学好弄的,但加上也无所谓,我们就能判断ac.addBeanFactoryPostProcessor和ac.registerBeanDefinition的区别了)
public class MyFacPostProcess_ShouDongZhuRu
implements BeanFactoryPostProcessor{
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===手动注入的MyFacPostProcess.postProcessBeanFactory()被执行。。。");
int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
}
}
public class MyBeanDefinitionRegistryPostProcessor_ShouDongZhuRu
implements BeanDefinitionRegistryPostProcessor{
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("===手动注入的MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()执行。。。");
int count = registry.getBeanDefinitionCount();//bean定义的数量
String[] names = registry.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
GenericBeanDefinition genericBeanDefinition =
new GenericBeanDefinition() ;
genericBeanDefinition.setBeanClass(Blue.class);
registry.registerBeanDefinition("bule1",genericBeanDefinition);
}
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("===手动注入的MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()执行。。。");
int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
}
}
2 配置类
为了能扫描到上面的注解,我们定义配置类并扫描,此外在里面@Bean一个普通的car对象
@Configuration // 告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu")
public class MainConfigFacPostProcesser {
// 简单注入一个bean,观察执行时机
@Bean
Car Car1(){
return new Car();
}
}
3 启动类的改写
我们的启动类一般的写法是new AnnotationConfigApplicationContext(Config.class)
这样子,但我们看一下他源码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
他分为了三个步骤,为了后续解释的需要,我们给他们分开写。另外我们应该意识到,在下面加注释就是在上面加注释,执行时机都是一样的。我们加了6个关键点,为了观察工厂的状态
- 比较ac.registerBeanDefinition和ac.addBeanFactoryPostProcessor方法的区别
public class MainTest1 {
public static void main(String[] args) {
// 1 去初始化工厂
// 打断点。下面这句就是创建了一个空工厂
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
// 2 debug执行完上句发现bd map中有5个:
// annotation.internalConfigurationAnnotationProcessor,实现了BeanDefinitionRegistryPostProcessor
// annotation.internalAutowiredAnnotationProcessor,实现了BeanPostProcessor
// annotation.internalCommonAnnotationProcessor,实现了BeanPostProcessor
// event.internalEventListenerProcessor,实现了BeanFactoryPostProcessor
// event.internalEventListenerFactory,实现了EventListenerFactory
// 注册bean定义,而不是注册bean
// 注册 bd注册器
GenericBeanDefinition mygenericBD_BDRegistry_shoudongZhuCe = new GenericBeanDefinition();
// 设置class
mygenericBD_BDRegistry_shoudongZhuCe.setBeanClass(MyBeanDefinitionRegistryPostProcessor_ShouDongZhuRu.class);
ac.registerBeanDefinition("mygenericBD_BDRegistry_shoudongZhuCe",mygenericBD_BDRegistry_shoudongZhuCe);
// 3 刚执行完上句,还没执行下句,bd map中bd个数由5变为6.此时还没有实例化bean
// 注册普通工厂后置处理器
GenericBeanDefinition mygenericBD_FacPostPro_shoudongZhuCe = new GenericBeanDefinition();
mygenericBD_FacPostPro_shoudongZhuCe.setBeanClass(MyFacPostProcess_ShouDongZhuRu.class);
// 调用的是registerBeanDefinition方法
ac.registerBeanDefinition("mygenericBD_FacPostPro_shoudongZhuCe",mygenericBD_FacPostPro_shoudongZhuCe);
// 4 bd个数变为7
ac.register(MainConfigFacPostProcesser.class);
// 下面4行并不往bd map中添加,而是直接添加到了工厂中
RuCanBeanDefinitionRegistryPostProcessor ruCanBeanDefinitionRegistryPostProcessor =
new RuCanBeanDefinitionRegistryPostProcessor();
RuCanBeanFactoryPostProcessor ruCanBeanFactoryPostProcessor = new RuCanBeanFactoryPostProcessor();
// 调用的是add方法
ac.addBeanFactoryPostProcessor(ruCanBeanDefinitionRegistryPostProcessor);// 注意不要使用registerBean,得使用addBeanFactoryPostProcessor
ac.addBeanFactoryPostProcessor(ruCanBeanFactoryPostProcessor);
// 5 bd个数变为8
// 打断点 初始化容器
ac.refresh();
// 6
System.out.println(1);
}
}
三、观察bd map变化
为了清晰,还改了下IDEA主题。。。
- 容器首先注入内置的工厂后置处理器bd
如上所示,spring中工厂什么都没做时,内置的是5个bd
然后我们手动注入两个接口的工厂后置处理器实现类
如图,扫描完我们的一个bd后,工厂中bd新增至6个,后面再扫描一个我们的,就变为7个
再手动注册我们的配置类
注意我们通过ac.addBeanFactoryPostProcessor注册的工厂后置处理器并不在bd map中
执行完refresh。。。那bean就更多了。。。
四、观察工厂后置处理器的执行时机
ac工厂在刷新的时候,先实例化工厂后置处理器,然后调用他们的方法,这样就可以注册除工厂后置处理器类型的bd
我们把手动注册的和注解注册的重写的每个工厂后置处理器的每个方法都打上断点,先观察一遍他们的执行顺序,我debug得到的顺序如下:
- 先执行
DefinitionRegistryPostProcessor.新增bd定义
方法- 入参的一个方法RuCanBeanDefinitionRegistryPostProcessor .postProcessBeanDefinitionRegistry 也就是手动注册的register的
- 内置类的一个方法ConfigurationClassPostProcessor .postProcessBeanDefinitionRegistry 也就是内置的
- 手动注册bd的一个方法mygenericBD_BDRegistry_shoudongZhuCe .postProcessBeanDefinitionRegistry() 也就是手动注册的,add的
- 有注解的一个方法MyBeanDefinitionRegistryPostProcessor_zhujie .postProcessBeanDefinitionRegistry 也就是扫描注解的
- 为什么是这个顺序:手动注册的肯定一下就找到了,而内置的是为了得到能扫描注解的东西,然后注解的就最后拿到了
- 后执行
DefinitionRegistryPostProcessor.修改bd定义
方法- 入参的第二个方法RuCanBeanDefinitionRegistryPostProcessor.postProcessBeanFactory
- 内置类的第二个方法ConfigurationClassPostProcessor.postProcessBeanFactory
- 手动注册bd的第二个方法mygenericBD_BDRegistry_shoudongZhuCe.postProcessBeanFactory
- 注解的第二个方法MyBeanDefinitionRegistryPostProcessor_zhujie.postProcessBeanFactory
- 最后执行
普通工厂后置处理器.修改bd定义
方法- 入参的.RuCanBeanFactoryPostProcessor.postProcessBeanFactory
- 手动注册的MyFacPostProcess_ShouDongZhuRu.postProcessBeanFactory
- 扫描注册的MyFacPostProcess_zhujie.postProcessBeanFactory()
总结优先级:
DefinitionRegistryPostProcessor
>BeanFactoryPostProcessor
。不管是哪里来的DefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
>DefinitionRegistryPostProcessor.postProcessBeanFactory
。先新增后修改bd- 结合前两者就是
DefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
>DefinitionRegistryPostProcessor.postProcessBeanFactory
>BeanFactoryPostProcessor.postProcessBeanFactory
- 入参>内置>手动注册>注解
五、ConfigurationClassPostProcessor初识
它是一个工厂后置处理器,用于扫描注解
先说下调用栈:
- refresh()
- invokeBeanFactoryPostProcessors()
- PostProcessorRegisterDelegate.invokeBeanFacoryPostProcessors()
再说下bd(bean definition)是一步步加载出来的,并不是一下就都拿到bd了。而工厂后置处理器的工作就是实例化工厂后置处理器的同时加载bd。容器已经发现的bd放到了bd map中
先看下这个图
图源自子路老师:https://blog.csdn.net/java_lyvee/article/details/102633067
他的意思是说:bd会在ac容器启动时,也就是我们调用栈中invokeBeanFacoryPostProcessors去执行ConfigurationClassPostProcessor
这个工厂后置处理器(实现了BeanDefinitionRegistryPostProcessor)的postProcessBeanDefinitionRegistry()
去完成bd的扫描,所以你去找到这个类的2个方法,也打上断点吧。现在我们就有了若干个工厂后置处理器实现方法的断点,我上面第四部分已经给出顺序:
好好品味一下,总结一下他们3个的优先级
再由下图看看ConfigurationClassPostProcessor
的重要性
CClassPP
ConfigurationClassPostProcessor
这里我们翻译为配置类后置处理器
,本文简写为CClassPP、CCPP
CCPP注册时机
CCPP在我们
- new启动类的
this()
方法里this.reader=new AnnatatedBeanDefinitionReader(this)
- –>
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
此时还没进入refresh()
方法就把CCPP
这个工厂后置处理器
放到了工厂中,即bd中
/// 由本处的继承关系可知CCPP是个工厂后置处理器
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
// CCPP在这个方法里完成了扫描、对配置类的定义、完成了配置类的标志、对@Import的处理、@ImportResource、@Bean、接口默认方法、处理@PropertySource 、内部类
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
@Import注解:会导入它自己这个bean,还会导入它的注解的一些bean
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c1E7xrLF-1630598979919)(…/…/…/…/…/AppData/Roaming/Typora/typora-user-images/image-20210515131843899.png)]
P1 环境搭建
P2 版本管理是通过父依赖的DB管理的
P3 导入第三方提供的starter时要自己指定版本号
P4 SpringBootConfiguration代表是个配置类。
P5 @EnableAutoConfiguration、介于@Import来导入相关bean。导入了AutoConfigurationPackages.Registrar.class只是注入了一个bean,还没有扫描。
P6、导入AutoConfigurationImportSelector,根据spring.factories导入bean,用config.removeAll(exclstions)排除需要排除的配置类,可以用@SpringbootApplication(exclude=)。
P7、filter(config,autoConfigurationMeta)排除掉无需自动配置的,执行完后configs个数减少了。用new AutoConfigEntry(configs,exclusions)将需要自动配置的类封装为AutoConfigEntry对象。最终放到AutoConfigrationGroup的属性中,process()执行完还没注入呢,在run()方法中才会注入bd。在selectImports()方法中又进行了过滤和排序,不是核心步骤。
P8、讲了一个字段编码的配置类案例
P9、@ComponentScan:用来扫描注解
P10、在new中根据类路径推断容器类型deduceFromClassPath()
P11、很多思想是都是从spring.factories里获取key对应的value
P12、SpringApplicationRunListeners负载在boot启动的不同阶段广播出不同的消息,传递给ApplicationListener监控实现类。这个监听器是EventPublishingRunListener
六、debug工厂后置处理器
不管是什么工厂后置处理器都分为3个等级,实现PriorityOrdered接口的>实现Ordered接口的,没有实现优先级接口的。而且不只是工厂后置处理器,就连普通bean都会按照这个逻辑走。
还记得上面的执行逻辑吗?我在这里多说一句,实例化的时候不仅会实例化工厂中的后置处理器,而且同期传入方法的参数不只有工厂,还有另外一个参数,他也是工厂后置处理器。他的优先级是比factory中其他工厂后置处理器优先级高的,他在所有BDregistry类型的工厂后置处理器执行完2个方法后,立马执行入参的工厂后置处理器,所以说他的优先级高。另外,因为我们已经执行完了该入参,那么就没必要记录他是否没执行过了,因为肯定执行过了。
再说明一下,factory中有三种bean:工厂后置处理器,后置处理器,普通bean。我们在实例化工厂后置处理器时是不实例化后2者的,也就是说我们把后置处理器和普通bean的bd扫描出来而已,只是new bd,不是new bean。new 工厂是后面的工作,new 普通bean更是最后的最后才做。
另外有几个map了解一下:
- processedBeans集合:因为工厂后置处理器是分批实例化的,这个集合就记录了已经实例化过的工厂后置处理器
- currentRegistryProcessors集合:现在正在处理的后置处理器bean,他会拿到bean定义先实例化【getBean】,再放到集合中,然后去调用该工厂后置处理器的方法。注意是工厂后置处理器这个bean
- registryProcessors集合:保存所有已经实例化好的工厂后置处理器
// PostProcessorRegistrationDelegate;
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, // 正在创建的工厂
List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {//这个参数进来时候都为空
// Invoke BeanDefinitionRegistryPostProcessors first, if any. 存储已经处理完成的BeanFactoryPostProcessor
Set<String> processedBeans = new HashSet<String>();
// 1.判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,
// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此进入if
if (beanFactory instanceof BeanDefinitionRegistry) {//如果这个工厂是bean定义注册工厂,那么这个工厂不仅作用于注册bean定义前后,还作用于bean定以后的工厂初始化前
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;//强转,registry是工厂
// 初始化两个list,观察名字就可以知道作用
// 实现BeanFactoryPostProcessor(那么实现BeanDefinitionRegistryPostProcessor的也在里面)
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();//存放普通的"工厂"后置处理器
// 实现接口BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();//存放"bean定义工厂"后置处理器
//2.这里一般不进入,但程序员在refresh前加了ac.addBeanFactoryPostProcessor()就进入了
// 这里的意思是说,先执行入参beanFactoryPostProcessors的方法,他优先级最高了(但也得遵守方法优先级的问题)
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 2.1 如果这个工厂后置处理器是BeanDefinitionRegistryPostProcessor
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 2.1.1 直接执行入参的postProcessBeanDefinitionRegistry()方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 2.1.2 添加到registryProcessors-list(用于最后执行postProcessBeanFactory方法)
registryProcessors.add(registryProcessor);
}
else {//入参只是普通的BeanFactoryPostProcessor
// 2.2 入参只是普通的BeanFactoryPostProcessor,先添加到regularPostProcessors,
// 后面再执行postProcessBeanFactory方法,防止顺序乱了,比较registry肯定优先级高
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();//临时变量,存放本次要执行的工厂后置处理器BeanDefinitionRegistryPostProcessor,往下看就明白了,在下一次使用前clear//
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.// 3.调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类。这里只是拿到spring内置的
// 3.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的后置处理器Bean的beanName。
// 这里只会拿到ConfigurationAnnotationProcessor,但是我们在main中手动注册了1个,所以拿到2个
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 3.2 遍历ConfigurationAnnotationProcessor和手动注册的registry的工厂后置处理器
for (String ppName : postProcessorNames) {
// 3.3 校验是否实现了PriorityOrdered接口,但是我们的手动注册工厂后置处理器没有实现这个,所以不进入
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//3.4 getBean用于实例化工厂后置处理器
// 这里只会实例化ConfigurationAnnotationProcessor
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 3.5 记录好实例化好的工厂后置处理器
processedBeans.add(ppName);
}
}
// 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 3.7 注册后置处理器到registryProcessors(用于最后执行postProcessBeanFactory方法)
registryProcessors.addAll(currentRegistryProcessors);
// 3.8 ***遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry()方法。我们之前只是实例化了ConfigurationAnnotationProcessor对象,还没有调用该对象重写的方法呢,我们当然得调用他们的方法了。但是我们手动注入的还没实例化呢,当然不在这里调用。对于ConfigurationAnnotationProcessor,我们后面会说
// 我们还把入参形成的registry也传进去,他也去执行postProcessBeanDefinitionRegistry()方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 好家伙,执行完上句之后,直接把我们注解的bd全扫描到了
// 3.9 执行完毕后, 清空currentRegistryProcessors-list
currentRegistryProcessors.clear();
// 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类
//(过程跟上面的步骤3基本一样,重复一遍而已,但我们代码中没有这种类型,跳过)
// 值得注意的是因为Config...扫描了很多bd,所以我们得重写拿到现有bd
// 还有注意虽然我们可能重复拿到工厂后置处理器,但因为有processedBeans的判断,可以免于重复执行
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 同样附加传入了入参形成的registry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors
// 也就是没有实现优先级接口的。我们的BDRegistry...类都是在这里执行,也没什么好说的,跳过
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
// 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor,
// 因此这边将reiterate赋值为true, 代表需要再循环查找一次
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 5.4 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 上面只调用完了BDregistry...里的一个方法,他里面还有一个方法需要我们去执行
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 6.***调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory
// 7.最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
// 这里还得多说一句,注意是入参中传过来的的,不是工厂中的后置处理器
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//--------------跳出if,,else...
// 到这里 , 入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,下面开始处理容器中的所有BeanFactoryPostProcessor
8.找出所有实现BeanFactoryPostProcessor接口的类
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
// 8.1 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {//已经执行过了就跳过
// skip - already processed in first phase above
}
// 8.3 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// 8.4 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 9.调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor
// 9.1 对priorityOrderedPostProcessors排序
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 9.2 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 10.调用所有实现Ordered接口的BeanFactoryPostProcessor
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
// 10.1 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 10.2 对orderedPostProcessors排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// 10.3 遍历orderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 11.调用所有剩下的BeanFactoryPostProcessor
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
// 11.1 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 11.2 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);//MyBeanFactoryPostProcessor.postProcessBeanFactory
// 12.清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
七、解读ConfigurationClassPostProcessor
不想看了。。。肯定是一堆扫描注解
1 postProcessBeanDefinitionRegistry()
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 进入 扫描注解
processConfigBeanDefinitions(registry);
}
2 postProcessBeanFactory()
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
1.1 processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// bd集合
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 处理主类
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
2.1 enhanceConfigurationClasses
/**
* Post-processes a BeanFactory in search of Configuration class BeanDefinitions;
* any candidates are then enhanced by a {@link ConfigurationClassEnhancer}.
* Candidate status is determined by BeanDefinition attribute metadata.
* @see ConfigurationClassEnhancer
*/
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
八、其他问题
1 AOP的@EnableAspectAutoProxy时机
上面解释过了ConfigurationClass…那个工厂后置处理器扫描进来的,我们去看看
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
这个注解@Import了个register,去里面看看,注解驱动开发的知识告诉我们肯定实现了registerBeanDefinitions方法,他用来注册bd
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 去里面看看,他是在里面注册bd的
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
一路委托,最终委托到,好家伙,我们终于看到new RootBeanDefinition了,这不就是new bd。他里面打个断点自己看吧
// AopConfigUtils.java
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls,
BeanDefinitionRegistry registry,
@Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
我们通过debug发现他就是new bd(AnnotationAwareAspectJAutoProxyCreator
.class)
我们进AnnotationAwareAspectJAutoProxyCreator
类去看,他实现了SmartInstantiationAwareBeanPostProcessor接口,他是个后置处理器,他会在refresh的下个阶段进行实例化。
更详细的内容看下一篇吧
2 想要整合其他源码怎么做
把第三方源码的工厂后置处理器作为入参传入到处理工厂后置处理器的逻辑中,他会在这个阶段完成逻辑
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
未整理内容
AnnotatedBeanDefinitionReader:
① 启动main方法,在main方法里面调用
②AnnotationConfigApplicationContext的无参构造方法,然后②-1
在无参构造方法里面首先实例化AnnotatedBeanDefinitionReader对象,实例化这个对象有两个非常重要的意义。 1、这个对象实例化出来有什么用(问题一) ; 2、实例化这个对象的过程中做了哪些事情(问题二)
继而②-2spring又实例化了一个ClassPathBeanDefinitionScanner对象,这个对象顾名思义就是能够用来完成spring的扫描功能,但是这里提一句——spring内部完成扫描功能并不是用的这个对象,而是在扫描的时候又new了一个新的ClassPathBeanDefinitionScanner对象;换言之这里spring new的对象我们假设他为a,但是spring在真正完成扫描的时候又new了一个b,但是是同一个类都是ClassPathBeanDefinitionScanner,但是为什么需要两个? 3、直接用a不就可以了吗?如果spring内部完成扫描时候没用a,那么a被new出来在哪里使用了?(问题三)到此为止第②步完成;
③调用register(Appconfig.class);
首先会把Appconfig类解析成为一个beanDefintion对象【这里只是配置类的bean定义对象,不是其他单例bean】(如何把一个类解析称为beanDefinition对象的?这里其实涉及到②-1AnnotatedBeanDefinitionReader对象的意义,如果你明白了②-1这里也就明白了),然后给解析出来的beanDefinition对象设置一些默认属性,继而put到beanDefintionMap当中,spring后面会遍历这个map根据map当中的beanDefinition来实例化bean,如果Appconfig类的beanDefintion存在在map当中那么他必然会被spring容器实例化称为一个bean?为什么Appconfig会需要实例化呢?因为Appconfig当中有很多加了@Bean的方法,这些方法需要被调用,故而需要实例化,但是Appconfig类的实例化很复杂比一般类实例化过程复杂很多,涉及到代理涉及到cglib等等,这个我们后面文章解释;这里还需要解释一个问题,为什么Appconfig类是通过register(Appconfig.class);手动put到map当中呢?为什么不是扫描出来的呢?(一般类都是通过扫描出来的),其实也很简单,因为他无法扫描自己,一般类是spring通过解析Appconfig上的@ComponentScan注解然后被扫描到,所以无法扫描自己;接下来便是第
问题一:AnnotatedBeanDefinitionReader
问题一——AnnotatedBeanDefinitionReader这个对象实例化出来有什么用?
先看一下这个类的javadoc,看看作者怎么来解释这个类的
/**
* Convenient adapter for programmatic registration of bean classes.
*
* <p>This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
* the same resolution of annotations but for explicitly registered classes only.
*
* @see AnnotationConfigApplicationContext#register
*/
public class AnnotatedBeanDefinitionReader {
按照笔者蹩脚的英文水平我的理解是:这个类作用分为以下两个
1、可用于编程式动态注册一个带注解的bean,什么意思呢?比如我们有一个类A存在com.shadow包下面,并且是一个加注解的类。比如加了@Component,正常情况下这个类A一般是被spring扫描出来的,但是有不正常情况,比如spring并没有扫描到com.shadow包,那么类A就无法被容器实例化。有人可能会问为什么没有扫描到com.shadow包?扫描情况下不会扫描到?其实很简单,假设你的这个类是动态生成,在容器实例化的时候不存在那么肯定不存在,再或者这个包下面有N多类但是只有一个类加了注解,那么其实你不需要去扫描,只需要添加这一个加了注解的类即可,再或者一个类是你和第三方系统交互后得到的。那么这个时候我们可以把这个类通过AnnotatedBeanDefinitionReader的register(Class clazz)方法把一个带注解的类注册给spring(这里的注册其实就是上一篇文章中说的把一个类解析成BeanDefintion对象,然后把这个对象put到beanDefinitionMap当中),写个例子来测试一下他的这个注册bean的功能
2、可以代替ClassPathBeanDefinitionScanner
这个类,具备相同的注解解析功能, ClassPathBeanDefinitionScanner是spring完成扫描的核心类,这个我后面会分析;简而言之,spring完成扫描主要是依靠ClassPathBeanDefinitionScanner这个类的对象,但是AnnotatedBeanDefinitionReader可以替代他完成相同的注解解析,意思就是通过ClassPathBeanDefinitionScanner扫描出来的类A和通过AnnotatedBeanDefinitionReader显示注册的类A在spring内部会一套相同的解析规则;这点上面那个例子已经证明了。
那么AnnotatedBeanDefinitionReader除了动态显示注册一些spring扫描不到的类之外还有什么功能?在初始化spring容器的过程中他主要干了什么事情呢?或者这么说:假设程序中没有需要动态显示注册的类他就没用了吗?再或者AnnotatedBeanDefinitionReader这个类的对象除了注册一些自己的类还有什么应用场景呢?——注册我们的配置类,对于不理解是什么配置的读者可以理解所谓的配置类就是那个加了@Configuration和@ComponentScan的那个类,也就是Appconfig.java;
那么问题来了,为什么配置类需要手动注册呢?很简单因为配置类无法扫描出来,所以需要我们手动注册。为什么无法扫描呢?比如spring完成扫描是需要解析Appconfig.java当中的@ComponentScan注解的值(一般是一个包名),得到这个值之后去扫描这个值所代表的包下面的所有bean;简单的说就是spring如果想要完成扫描必须先提供Appconfig.java,所以Appconfig.java要在一开始就手动注册给spring,spring得到Appconfig.class之后把他解析成BeanDefintion对象,继而去获取@ComponentScan的值然后才开始扫描其他bean;
总结:AnnotatedBeanDefinitionReader的作用1、主要是可以动态、显示的注册一个bean;2、而且具备解析一个类的功能;和扫描解析一个类的功能相同;AnnotatedBeanDefinitionReader的应用场景1、可以显示、动态注册一个程序员提供的bean;2、在初始化spring容器的过程中他完成了对配置类的注册和解析功能;
针对AnnotatedBeanDefinitionReader应用场景的第2点,我在啰嗦几句,一般程序员在初始化spring容器的时候代码有很多种写法,但都是换汤不换药的,我这里举2个栗子。
最后
以上就是文艺鸡翅为你收集整理的【spring源码】五、工厂后置处理器BeanFactoryPostProcessor【重要】的全部内容,希望文章能够帮你解决【spring源码】五、工厂后置处理器BeanFactoryPostProcessor【重要】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复