SpringBoot @Resource注入的坑

一、场景复现

双kafka消费者配置

(1)第一个kafka

public class OneKafkaConfig {

    @Bean
    public KafkaListenerContainerFactory oneKafkaFactory(@Resource ConsumerFactory oneConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(oneConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Bean
    public ConsumerFactory oneConsumerFactory(@Resource KafkaProperties oneKafkaProperties){
        return new DefaultKafkaConsumerFactory(oneKafkaProperties.buildConsumerProperties());
    }


    @ConfigurationProperties(prefix = "sys.kafka.one")
    @Bean
    public KafkaProperties oneKafkaProperties(){
        return new KafkaProperties();
    }

 (2)第二个kafka

public class TwoKafkaConfig {


    @Bean
    public KafkaListenerContainerFactory twoKafkaFactory(@Resource ConsumerFactory twoConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(twoConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Primary
    @Bean
    public ConsumerFactory twoConsumerFactory(@Resource KafkaProperties twoKafkaProperties){

         return new DefaultKafkaConsumerFactory(twoKafkaProperties.buildConsumerProperties());
    }



    @Primary
    @ConfigurationProperties(prefix = "sys.kafka.two")
	@Bean
    public KafkaProperties twoKafkaProperties(){
       return new KafkaProperties();
    }
}

启动项目,发现两个kafka的消费者都是指向同一个kafka,@Resource没有根据名字注入所以依赖的bean。

二、分析原因

从debug模式下中发现:twoKafkaProperties、twoConsumerFactory、twoKafkaFactory依次创建。然后先是TwoConsumerFactory先注入创建oneKafkaFactory,而twoKafkaProperties bean先注入创建oneConsumerFactory,最后oneKafkaProperties才开始创建。

原因:@Resource注入之前先根据名字查询bean,找不到才根据类型进行bean注入。因为twoConsumerFactory为@Primary优先级高先创建,oneKafkaFactory创建的时候oneConsumerFactory 还没有创建,所以根据类型注入了twoConsumerFactory。

建议:多个类型相同的bean创建不要使用@Resource,应该使用@Autowired + @Qualifier或者重新继承bean的类型。

三、改造方式

(1)@Autowiredv+ @Qualifier


public class OneKafkaConfig {

    @Bean
    public KafkaListenerContainerFactory oneKafkaFactory(@Autowired @Qualifier("oneConsumerFactory") ConsumerFactory oneConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(oneConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Bean
    public ConsumerFactory oneConsumerFactory(@Autowired @Qualifier("oneKafkaProperties") KafkaProperties oneKafkaProperties){
        return new DefaultKafkaConsumerFactory(oneKafkaProperties.buildConsumerProperties());
    }


    @ConfigurationProperties(prefix = "sys.kafka.one")
    @Bean
    public KafkaProperties oneKafkaProperties(){
        return new KafkaProperties();
    }

}
public class TwoKafkaConfig {


    @Bean
    public KafkaListenerContainerFactory twoKafkaFactory(@Autowired @Qualifier("twoConsumerFactory") ConsumerFactory twoConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(twoConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Primary
    @Bean
    public ConsumerFactory twoConsumerFactory(@Autowired @Qualifier("twoKafkaProperties") KafkaProperties twoKafkaProperties){

         return new DefaultKafkaConsumerFactory(twoKafkaProperties.buildConsumerProperties());
    }


    @Primary
    @ConfigurationProperties(prefix = "sys.kafka.two")
    @Bean
    public KafkaProperties twoKafkaProperties(){
       return new KafkaProperties();
    }

}

(2)重新继承bean的类型

public class OneKafkaConfig {

    @Bean
    public KafkaListenerContainerFactory oneKafkaFactory(@Autowired OneConsumerFactory oneConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(oneConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Bean
    public OneConsumerFactory oneConsumerFactory(@Autowired OneKafkaProperties oneKafkaProperties){
        return new OneConsumerFactory(oneKafkaProperties.buildConsumerProperties());
    }


    @ConfigurationProperties(prefix = "sys.kafka.one")
    @Bean
    public OneKafkaProperties oneKafkaProperties(){
        return new OneKafkaProperties();
    }
public class TwoKafkaConfig {


    @Bean
    public KafkaListenerContainerFactory twoKafkaFactory(@Autowired TwoConsumerFactory twoConsumerFactory) {
        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(twoConsumerFactory);
        factory.setConcurrency(10);
        factory.setBatchListener(true);
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);

        return factory;
    }

    @Primary
    @Bean
    public TwoConsumerFactory twoConsumerFactory(@Autowired TwoKafkaProperties twoKafkaProperties){

         return new TwoConsumerFactory(twoKafkaProperties.buildConsumerProperties());
    }



    @Primary
    @ConfigurationProperties(prefix = "sys.kafka.two")
	@Bean
    public TwoKafkaProperties twoKafkaProperties(){
       return new TwoKafkaProperties();
    }
}
发布了354 篇原创文章 · 获赞 522 · 访问量 128万+

猜你喜欢

转载自blog.csdn.net/moakun/article/details/104061482