带有事件侦听器的BeanFactory

时间:2018-07-10 17:10:56

标签: spring spring-bean

我正在使用ConfigurableListableBeanFactory和registerSingleton方法动态创建bean,之后我想使用EventListener监听事件。 在示例中,Kafka侦听器正确接收到消息,但未触发EventListener,这是因为BeanFactory不支持ApplicationEvents,那么如何将EventListener添加到BeanFactory?

致谢!

https://docs.spring.io/spring-framework/docs/4.3.9.RELEASE/spring-framework-reference/html/beans.html#beans-definition

    @PostConstruct
         public void setup() {
                final ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();

                kafkaConfiguration.getTopics().keySet().forEach(key -> {
                    Topic topic = kafkaConfiguration.getTopics().get(key);

                    DefaultKafkaConsumerFactory<String, KafkaEntity> defaultKafkaConsumerFactory = new DefaultKafkaConsumerFactory<>(
                            consumerConfigs(),
                            new StringDeserializer(),
                            new JsonDeserializer<>(topic.getClazz()));

                    beanFactory.registerSingleton(key, defaultKafkaConsumerFactory);

                    ConcurrentKafkaListenerContainerFactory<String, KafkaEntity> concurrentKafkaListenerContainerFactory =
                        new ConcurrentKafkaListenerContainerFactory<>();
                    concurrentKafkaListenerContainerFactory.setConsumerFactory(defaultKafkaConsumerFactory);
                    concurrentKafkaListenerContainerFactory.setConcurrency(topic.getConcurrency());
                    concurrentKafkaListenerContainerFactory.setAutoStartup(topic.isAutoStart());
concurrentKafkaListenerContainerFactory.getContainerProperties().setPollTimeout(kafkaConfiguration.getPollTimeout());
concurrentKafkaListenerContainerFactory.getContainerProperties().setIdleEventInterval(1000L);
      beanFactory.registerSingleton(CONTAINER_FACTORY_NAME + key, concurrentKafkaListenerContainerFactory);
        }

        @KafkaListener(id = "kfktest", topics = "data_common-apibridge-service.board", idIsGroup = false,
                containerFactory = KafkaConsumerConfiguration.CONTAINER_FACTORY_NAME + "BOARD")
        public void listen(@Payload(required = false) BoardMessage message,
                           @Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key) {
            // TODO message handler
        }

        @EventListener(condition = "event.listenerId.startsWith('kfktest-')")
        public void eventHandler(ListenerContainerIdleEvent event) {
                log.info(event.getListenerId());
        }

1 个答案:

答案 0 :(得分:0)

经过一些阅读后,我发现了如何做到这一点,我使用了BeanFactoryPostProcessor来动态定义配置服务器中所有的bean,例如:

public static BeanFactoryPostProcessor beanFactoryPostProcessor(@Value("${kafka.topicNames}") String topicNames) {

此后,我使用@Postconstruct在另一个@Configuration中完成Bean,以便已实例化某些依赖项。

@Bean
    public static BeanFactoryPostProcessor beanFactoryPostProcessor(@Value("${kafka.topicNames}") String topicNames) {
        return beanFactoryPostProcessor -> {

            BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactoryPostProcessor;

            List<String> topics = Arrays.asList(topicNames.split(Pattern.quote(",")));
            topics.forEach(key -> {
                beanDefinitionRegistry.registerBeanDefinition(KafkaConsumerConfiguration.DEFAULT_KAFKA_CONSUMER_FACTORY_NAME + key,
                    BeanDefinitionBuilder.genericBeanDefinition(KafkaConsumerFactory.class)
                        .getBeanDefinition());

                beanDefinitionRegistry.registerBeanDefinition(KafkaConsumerConfiguration.CONTAINER_FACTORY_NAME + key,
                    BeanDefinitionBuilder.genericBeanDefinition(ConcurrentKafkaListenerContainerFactory.class)
                        .getBeanDefinition());
            });
            log.info("Topics bean defined {}", topics.size());
        };
    }

致谢!