spring 动态注册的Bean导致关闭挂接中出现异常

mmvthczy  于 2022-11-21  发布在  Spring
关注(0)|答案(1)|浏览(166)

在Sping Boot 应用程序中,我根据应用程序启动后收到的主题名称启动了一个Kafka侦听器容器。然而,我的问题可能不是关于Kafka,而是关于一般的动态注册bean。

private volatile KafkaMessageListenerContainer<String,String> adminMessageListenerContainer;
private final Object threadLock = new Object();
...
...
private void startAdminMessageListener(Message heartbeat) {
  final String topic = heartbeat.getMessageTopicPrefix() + "-" + applicationClusterName;
  if (adminMessageListenerContainer == null) {
    synchronized (threadLock) {
      if (adminMessageListenerContainer == null) {
        final KafkaMessageListenerContainer<String,String> container = createAdminMessageLister(topic);
        applicationContext.registerBean("adminMessageListenerContainer", KafkaMessageListenerContainer.class, container);
        container.start();
        adminMessageListenerContainer = container;
        log.info("Starting admin message listener on topic {}", topic);
      }
    }
  }
}

这样做效果很好,只是当我停止应用程序时,会出现以下异常:

2022-11-18 13:59:30.861  WARN 67015 --- [ionShutdownHook] ConfigServletWebServerApplicationContext : Exception thrown from LifecycleProcessor on context close

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'adminMessageListenerContainer': Unsatisfied dependency expressed through constructor parameter 1: Ambiguous argument values for parameter of type [org.springframework.kafka.core.ConsumerFactory] - did you specify the correct bean references as arguments?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:787) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.10.jar:5.3.10]
    at org.springframework.context.support.DefaultLifecycleProcessor.getLifecycleBeans(DefaultLifecycleProcessor.java:285) ~[spring-context-5.3.10.jar:5.3.10]
    at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:191) ~[spring-context-5.3.10.jar:5.3.10]
    at org.springframework.context.support.DefaultLifecycleProcessor.onClose(DefaultLifecycleProcessor.java:129) ~[spring-context-5.3.10.jar:5.3.10]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1067) ~[spring-context-5.3.10.jar:5.3.10]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.doClose(ServletWebServerApplicationContext.java:172) ~[spring-boot-2.5.5.jar:2.5.5]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1021) ~[spring-context-5.3.10.jar:5.3.10]
    at org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:137) ~[spring-boot-2.5.5.jar:2.5.5]
    at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
    at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:106) ~[spring-boot-2.5.5.jar:2.5.5]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

我怎么才能避免呢?

qnakjoqk

qnakjoqk1#

更新

按照下面的建议创建我自己的bean类毕竟不是解决方案。事实证明,修复实际上是从Sping Boot 2.5.5升级到2.7.5。

以下错误

我通过创建我的所有者bean类来解决这个问题,其中的默认构造函数从包含的spring组件中获取超级构造函数的依赖项:

public class AdminMessageListenerContainer extends KafkaMessageListenerContainer<String, String> {
  public AdminMessageListenerContainer() {
    super(adminKafkaConsumerFactory, adminMessageListenerContainerProperties);
  }
}

然后再

private void startAdminMessageListener(Message heartbeat) {
  final String topic = heartbeat.getMessageTopicPrefix() + "-" + applicationClusterName;
  if (adminMessageListenerContainer == null) {
    synchronized (threadLock) {
      if (adminMessageListenerContainer == null) {
        this.adminMessageListenerContainerProperties = getAdminMessageListenerContainerProperties(topic);
        final AdminMessageListenerContainer container = new AdminMessageListenerContainer();
        applicationContext.registerBean("adminMessageListenerContainer", AdminMessageListenerContainer.class, container);
        container.start();
        adminMessageListenerContainer = container;
        log.info("Starting admin message listener on topic {}", topic);
      }
    }
  }
}

相关问题