本文解决的问题点:
1、自定义的kafkaTemplate()方法没有执行
2、加了注解@Bean没有执行
背景
不用springboot 自动装配的kafka,想自定义kafka template,就是自己注入kafka的配置参数,如
@Configuration public class KafkaConfig {
@Value("${kafka.broker.list}")
private String bootstrapServer;
@Value("${kafka.consumer.group.id}")
private String groupId;
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
//创建配置的Map
Map<String, Object> properties = new HashMap<>();
//kafka集群地址 [ host:port,host:port ]
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer);
//key 对应的序列化方式
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
//value 对应的序列化方式
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
//设置是否接收反馈,value必须设置为字符串类型的 1
properties.put(ProducerConfig.ACKS_CONFIG, "1");
//设置重试次数
properties.put(ProducerConfig.RETRIES_CONFIG, 0);
//设置批处理缓冲大小
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 20000000);
//设置生产者缓冲区大小
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
//设置clientId,用于发送给客户端的字符串,用于找日志
properties.put(ProducerConfig.CLIENT_ID_CONFIG, "kafka.client.demo.id");
//设置客户端请求的超时时间
properties.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 60000);
//创建ProducerFactory
ProducerFactory<String, String> producerFactory = new DefaultKafkaProducerFactory<>(properties);
//创建KafkaTemplate
KafkaTemplate<String, String> kafkaTemplate = new KafkaTemplate<>(producerFactory);
//返回
return kafkaTemplate;
} }
按理来讲,这里类加了@Configuration
方法上也加了@Bean
服务启动的之后这个方法 kafkaTemplate() 应该被执行,可是却死活没有进来,各种排查,无效!
解决办法
在服务启动类加上配置
@SpringBootApplication(exclude = KafkaAutoConfiguration.class)
原因
经排查spring执行了自动装配
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration#kafkaTemplate
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({KafkaTemplate.class})
@EnableConfigurationProperties({KafkaProperties.class})
@Import({KafkaAnnotationDrivenConfiguration.class, KafkaStreamsAnnotationDrivenConfiguration.class})
public class KafkaAutoConfiguration {
private final KafkaProperties properties;
public KafkaAutoConfiguration(KafkaProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean({KafkaTemplate.class})
public KafkaTemplate<?, ?> kafkaTemplate(ProducerFactory<Object, Object> kafkaProducerFactory, ProducerListener<Object, Object> kafkaProducerListener, ObjectProvider<RecordMessageConverter> messageConverter) {
KafkaTemplate<Object, Object> kafkaTemplate = new KafkaTemplate(kafkaProducerFactory);
messageConverter.ifUnique(kafkaTemplate::setMessageConverter);
kafkaTemplate.setProducerListener(kafkaProducerListener);
kafkaTemplate.setDefaultTopic(this.properties.getTemplate().getDefaultTopic());
return kafkaTemplate;
}
因此自定义的bean就没有执行,因为spring配置了冲突只加载一个
spring:
main:
allow-bean-definition-overriding: true
所以我们要禁止这个自动装配
只需在启动类上加
@SpringBootApplication(exclude = KafkaAutoConfiguration.class)
延伸
类似的redis,mq,mysql等需要自定义的可以去掉自动装配,避免别冲掉
@SpringBootApplication(exclude = RedisAutoConfiguration.class)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
// 多个时可以这样
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})