说明
在上篇博文《springboot学习(十六):了解springboot自动装配kafka原理》中,我对springboot自动装配kafka的原理进行了简单介绍,在文末说到springboot通过初始化配置类org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration实现了对kafa的自动装配。而该类又通过注解间接引入了spring-kafka的支持,在spring-kafka中的配置类KafkaBootstrapConfiguration又创建了两个bean,name分别为org.springframework.kafka.config.internalKafkaListenerAnnotationProcessor和org.springframework.kafka.config.internalKafkaListenerEndpointRegistry。
本篇博文将继续通过spring-kafka的源码,来了解spring-kafka是如何配置操作kafka的。
正文
KafkaListenerAnnotationBeanPostProcessor
在KafkaBootstrapConfiguration类中创建了名为org.springframework.kafka.config.internalKafkaListenerAnnotationProcessor的bean,该类实际为KafkaListenerAnnotationBeanPostProcessor。
通过源码可以看到该类实现了BeanPostProcessor和SmartInitializingSingleton两个接口:
分别实现了BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization两个接口,SmartInitializingSingleton的afterSingletonsInstantiated接口。从方法名称可以看出这几个方法都跟bean的初始化有关,但是这几个方法的调用顺序是怎么样的?
我们可以从加载bean的源码中了解以上方法的执行顺序。还是从AbstractApplicationContext类的refresh()方法入手:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory); // 注册BeanPostProcessor
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory); // 在该方法中实现bean的初始化
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
通过registerBeanPostProcessors方法实现对BeanPostProcessors的注册,在finishBeanFactoryInitialization方法中对bean进行了初始化,通过以下代码可以看到,在所有的bean都初始化结束后,才会对SmartInitializingSingleton类型的bean进行处理,调用afterSingletonsInstantiated()方法。
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
while(true) {
String beanName;
Object bean;
do {
while(true) {
RootBeanDefinition bd;
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
while(var2.hasNext()) {
beanName = (String)var2.next();
Object singletonInstance = this.getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, this.getAccessControlContext());
} else {