// 启动测试类
@Test
public void TestMain(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
// 待注入的bean
public class User {
}
// BeanDefinitionRegistryPostProcessor实现类
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
System.out.println(“MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry”);
System.out.println(“bean的数量:”+ beanDefinitionRegistry.getBeanDefinitionCount());
// 通过bean的构建器生成rootbean
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition(“hello”,beanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println(“MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory”);
System.out.println(“bean的数量:” + configurableListableBeanFactory.getBeanDefinitionCount());
}
}
// 配置类
@Configuration
@ComponentScan(“postprocessor”)
public class AppConfig {
}
可以看到输出结果如下,从中我们可以看出:
- 先执行postProcessBeanDefinitionRegistry方法,获取到IOC容器中bean的数量为7
- 然后给Registry里面注册一个hello
- 再执行postProcessBeanFactory方法,由于上面又注册了一个,所以这里获取到IOC容器中bean的数量为8
- 等BeanDefinitionRegistryPostProcessor里面的方法都执行完后,再执行BeanFactoryPostProcessor里面的方法
三、源码分析
同样,我们通过Debug的方式来分析源码,在postProcessBeanDefinitionRegistry方法处打个断点,启动断点调试,根据方法调用栈来进行跟踪:
通过查看方法调用栈,可以作出如下分析:
- 启动IOC容器调用refresh方法
- 再依次调用invokeBeanFactoryPostProcessors()——>invokeBeanDefinitionRegistryPostProcessors()方法
- 在invokeBeanDefinitionRegistryPostProcessors方法中获取到currentRegistryProcessors参数
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
…
// 获取到BeanDefinitionRegistryPostProcessor组件
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
var16 = postProcessorNames;
var9 = postProcessorNames.length;
for(var10 = 0; var10 < var9; ++var10) {
ppName = var16[var10];
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 获取currentRegistryProcessors参数
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
…
while(reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var19 = postProcessorNames;
var10 = postProcessorNames.length;
for(int var26 = 0; var26 < var10; ++var26) {
String ppName = var19[var26];
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 1.在这个方法里面触发postProcessBeanDefinnitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// 2.在这个方法里面触发postProcessBeanFactory方法
invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
…
// 3.在这个方法里面触发postProcessorBeanFactory方法
invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
…
}
从源码可以看到:
- 先获取BeanDefinitionRegistryPostProcessor组件
- 再按照一定规则(如优先级)加入到currentRegistryProcessors数组中
- currentRegistryProcessors作为参数传给invokeBeanDefinitionRegistryPostProcessors方法,最后在这个方法执行
- 下图可以看到此时已经将自己写的MyBeanDefinitionRegistryPostProcessor组件给获取到了
【1】触发BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
进入invokeBeanDefinitionRegistryPostProcessors方法,可以看到,在这里获取到组件并触发了postProcessBeanDefinitionRegistry:
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
Iterator var3 = postProcessors.iterator();
while(var3.hasNext()) {
BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var3.next();
StartupStep var10000 = applicationStartup.start(“spring.context.beandef-registry.post-process”);
postProcessor.getClass();
StartupStep postProcessBeanDefRegistry = var10000.tag(“postProcessor”, postProcessor::toString);
// 触发postProcessBeanDefinnitionRegistry
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
【2】触发BeanDefinitionRegistryPostProcessor组件的BeanFactoryPostProcessor#postProcessBeanFactory
在invokeBeanDefinitionRegistryPostProcessors方法执行完后,通过invokeBeanFactoryPostProcessors方法执行postProcessBeanFactory,点进源码进行查看:
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
StartupStep var10000 = beanFactory.getApplicationStartup().start(“spring.context.bean-factory.post-process”);
postProcessor.getClass();
StartupStep postProcessBeanFactory = var10000.tag(“postProcessor”, postProcessor::toString);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
Kafka实战笔记
关于这份笔记,为了不影响大家的阅读体验,我只能在文章中展示部分的章节内容和核心截图
- Kafka入门
- 为什么选择Kafka
- Karka的安装、管理和配置
- Kafka的集群
- 第一个Kafka程序
afka的生产者
- Kafka的消费者
- 深入理解Kafka
- 可靠的数据传递
- Spring和Kalka的整合
- Sprinboot和Kafka的整合
- Kafka实战之削峰填谷
- 数据管道和流式处理(了解即可)
- Kafka实战之削峰填谷
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
转存中…(img-1ocQqR87-1713333480935)]
- Spring和Kalka的整合
- Sprinboot和Kafka的整合
- Kafka实战之削峰填谷
- 数据管道和流式处理(了解即可)
[外链图片转存中…(img-20BUfVEX-1713333480935)]
- Kafka实战之削峰填谷
[外链图片转存中…(img-cQ6eTfI4-1713333480936)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!