alibaba / spring-cloud-alibaba

Spring Cloud Alibaba provides a one-stop solution for application development for the distributed solutions of Alibaba middleware.
https://sca.aliyun.com
Apache License 2.0
27.95k stars 8.34k forks source link

The spring-cloud-starter-stream-rabbit jar package conflict with spring-cloud-starter-alibaba-nacos-discovery #1061

Open Gcsimple opened 4 years ago

Gcsimple commented 4 years ago

Which Component spring-cloud-starter-alibaba-nacos-discovery,spring-cloud-starter-alibaba-nacos-config

Describe the bug spring-cloud-starter-stream-rabbit:2.1.3.RELEASE conflict with spring-cloud-starter-alibaba 2.1.0.RELEASE,can not run the server

Expected behavior run success

Screenshots ` org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'org.springframework.amqp.rabbit.config.internalRabbitListenerEndpointRegistry': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:208) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.getLifecycleBeans(DefaultLifecycleProcessor.java:289) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:195) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.stop(DefaultLifecycleProcessor.java:116) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.stop(AbstractApplicationContext.java:1353) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.doStop(DefaultLifecycleProcessor.java:251) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.access$300(DefaultLifecycleProcessor.java:53) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.stop(DefaultLifecycleProcessor.java:377) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:210) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.DefaultLifecycleProcessor.onClose(DefaultLifecycleProcessor.java:128) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1018) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:975) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:1.8.0_201] at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_201] at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1628) ~[na:1.8.0_201] at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_201] at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_201] at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:1.8.0_201] at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:1.8.0_201] at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_201] at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[na:1.8.0_201] at org.springframework.cloud.stream.binder.DefaultBinderFactory.destroy(DefaultBinderFactory.java:99) ~[spring-cloud-stream-2.1.3.RELEASE.jar:2.1.3.RELEASE] at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:258) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:571) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:543) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1036) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:504) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1029) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1057) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:562) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]

2019-11-15 15:43:14.136 INFO 5816 --- [ main] o.s.i.monitor.IntegrationMBeanExporter : Summary on shutdown: output 2019-11-15 15:43:14.136 INFO 5816 --- [ main] o.s.i.monitor.IntegrationMBeanExporter : Summary on shutdown: nullChannel 2019-11-15 15:43:14.136 INFO 5816 --- [ main] o.s.i.monitor.IntegrationMBeanExporter : Summary on shutdown: errorChannel 2019-11-15 15:43:14.136 INFO 5816 --- [ main] o.s.i.monitor.IntegrationMBeanExporter : Summary on shutdown: _org.springframework.integration.errorLogger.handler 2019-11-15 15:43:14.136 INFO 5816 --- [ main] c.a.c.d.s.DubboGenericServiceFactory : The Dubbo GenericService ReferenceBeans are destroying... 2019-11-15 15:43:14.136 INFO 5816 --- [ main] f.a.ReferenceAnnotationBeanPostProcessor : class org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor was destroying! 2019-11-15 15:43:14.136 INFO 5816 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2019-11-15 15:43:14.136 WARN 5816 --- [ main] o.a.c.loader.WebappClassLoaderBase : The web application [api] appears to have started a thread named [com.alibaba.nacos.naming.client.listener] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467) com.alibaba.nacos.client.naming.core.EventDispatcher$Notifier.run(EventDispatcher.java:114) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) java.lang.Thread.run(Thread.java:748) 2019-11-15 15:43:14.136 WARN 5816 --- [ main] o.a.c.loader.WebappClassLoaderBase : The web application [api] appears to have started a thread named [com.alibaba.nacos.naming.failover] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) java.lang.Thread.run(Thread.java:748) 2019-11-15 15:43:14.136 WARN 5816 --- [ main] o.a.c.loader.WebappClassLoaderBase : The web application [api] appears to have started a thread named [com.alibaba.nacos.naming.push.receiver] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method) java.net.DualStackPlainDatagramSocketImpl.receive0(DualStackPlainDatagramSocketImpl.java:124) java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:143) java.net.DatagramSocket.receive(DatagramSocket.java:812) com.alibaba.nacos.client.naming.core.PushReceiver.run(PushReceiver.java:73) java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) java.util.concurrent.FutureTask.run(FutureTask.java:266) java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) java.lang.Thread.run(Thread.java:748) 2019-11-15 15:43:14.152 WARN 5816 --- [ main] o.s.b.c.e.EventPublishingRunListener : Error calling ApplicationEventListener

java.lang.IllegalStateException: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@5ecce3 has not been refreshed yet at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1092) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1104) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.getTargetBean(ApplicationListenerMethodAdapter.java:288) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:258) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:179) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:142) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:158) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127) [spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.boot.context.event.EventPublishingRunListener.failed(EventPublishingRunListener.java:123) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplicationRunListeners.callFailedListener(SpringApplicationRunListeners.java:90) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplicationRunListeners.failed(SpringApplicationRunListeners.java:83) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:792) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 2019-11-15 15:43:14.152 INFO 5816 --- [ main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2019-11-15 15:43:14.339 INFO 5816 --- [ main] acosDiscoveryPropertiesAutoConfiguration :

Custom nacos metadata

2019-11-15 15:43:14.339 ERROR 5816 --- [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.client.discovery.DiscoveryClient' available at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:346) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:337) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.init(SpringCloudRegistryFactory.java:74) ~[spring-cloud-alibaba-dubbo-2.1.0.RELEASE.jar:2.1.0.RELEASE] at com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.getRegistry(SpringCloudRegistryFactory.java:84) ~[spring-cloud-alibaba-dubbo-2.1.0.RELEASE.jar:2.1.0.RELEASE] at org.apache.dubbo.registry.RegistryFactory$Adaptive.getRegistry(RegistryFactory$Adaptive.java) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.registry.integration.RegistryProtocol.getRegistry(RegistryProtocol.java:298) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.registry.integration.RegistryProtocol.export(RegistryProtocol.java:212) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:120) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:59) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:61) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:607) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:457) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:415) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:378) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.spring.ServiceBean.export(ServiceBean.java:336) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:114) ~[dubbo-2.7.3.jar:2.7.3] at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:60) ~[dubbo-2.7.3.jar:2.7.3] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] `

Gcsimple commented 4 years ago

已经解决,配置binder时如果使用覆盖的方式 ,再集成nacos会有问题 binders: rabbitmq: type: rabbit environment: spring: rabbitmq: host: 192.168.129.117 port: 5672 username: password:

tyq0010 commented 4 years ago

@gaochuanneu 我也遇到了同样的问题,请问一下,你最终是如何解决的?

Gcsimple commented 4 years ago

@gaochuanneu 我也遇到了同样的问题,请问一下,你最终是如何解决的? 不要使用配置覆盖的方式

fangjian0423 commented 4 years ago

I think this is a problem of Spring Cloud Stream and Spring Cloud Commons.

laiweijia commented 4 years ago

me too

Zze0 commented 3 years ago

@fangjian0423 @laiweijia @tyq0010 @gaochuanneu @mercyblitz 挖个坟,我有遇到上面说的问题,场景类似,但没有Bean的冲突。下面说下我的情况。

  1. Dubbo中的DubboServiceRegistrationApplicationContextInitializer类通过ApplicationContextInitializer方式来注入ApplicationContext应用上下文到SpringCloudRegistryFactory中。 spring-cloud-starter-dubbo-2.2.5.RELEASE.jar!\META-INF\spring.factories

  2. Spring Cloud项目启动,实例化各种Bean......(包括了DiscoveryClient)

  3. 在Spring Cloud Stream在处理自定义的Binder配置时,会为其特定的environment配置独立一个ApplicationContext应用上下文(这个有点特殊,时间原因,没有细究),然后会触发ApplicationContextInitializer,Dubbo中的DubboServiceRegistrationApplicationContextInitializer类就获取到了这个特殊的ApplicationContext应用上下文(这个是获取不到实例化好的Bean的)。

  4. SpringCloudRegistryFactory然后在注册Dubbo服务时,使用上一步获取到的ApplicationContext来getBean(DiscoveryClient.class),那自然就报错了。

import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.Optional;

@Component public class SpringUtils implements ApplicationContextAware {

private static ApplicationContext applicationContext = null;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    SpringUtils.applicationContext = applicationContext;
}

public static Optional<ApplicationContext> tryGetApplicationContext() {
    return Optional.ofNullable(applicationContext);
}

}

```java
package org.zze0;

import com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;

@Order
public class MyDubboServiceRegistrationApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        SpringUtils.tryGetApplicationContext()
                .filter(context -> context instanceof ConfigurableApplicationContext)
                .map(context -> (ConfigurableApplicationContext) context)
                .ifPresent(SpringCloudRegistryFactory::setApplicationContext);
    }
}

spring.factories:

org.springframework.context.ApplicationContextInitializer=\
  org.zze0.MyDubboServiceRegistrationApplicationContextInitializer
lwk595ww commented 3 years ago

@fangjian0423 @laiweijia @tyq0010 @gaochuanneu @mercyblitz 挖个坟,我有遇到上面说的问题,场景类似,但没有Bean的冲突。下面说下我的情况。

  • 异常

Dubbo自动关停自我销毁 11:39:12.242 [main] INFO o.a.d.r.t.AbstractServer - [,73] - [DUBBO] Start NettyServer bind /0.0.0.0:20880, export /10.10.10.2:20880, dubbo version: 2.7.8, current host: 10.10.10.2 11:39:12.264 [main] INFO c.a.c.d.s.DubboMetadataServiceExporter - [unexport,106] - The Dubbo service[] has been unexported. 11:39:12.266 [main] INFO o.a.d.r.s.AbstractRegistryFactory - [destroyAll,81] - [DUBBO] Close all registries [], dubbo version: 2.7.8, current host: 10.10.10.2 11:39:12.266 [main] INFO o.a.d.r.p.d.DubboProtocol - [destroy,615] - [DUBBO] Close dubbo server: /10.10.10.2:20880, dubbo version: 2.7.8, current host: 10.10.10.2 11:39:12.267 [main] INFO o.a.d.r.t.AbstractServer - [close,128] - [DUBBO] Close NettyServer bind /0.0.0.0:20880, export /10.10.10.2:20880, dubbo version: 2.7.8, current host: 10.10.10.2 然后抛出异常: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.client.discovery.DiscoveryClient' available

  • 环境

spring-cloud-stream-binder-kafka:3.0.8.RELEASE spring-cloud-starter-dubbo:2.2.5.RELEASE spring-cloud-dependencies:Hoxton.SR8 spring-cloud-alibaba-dependencies:2.2.5.RELEASE nacos-client: 2.0.0

  • 问题分析 共性是都用了spring.cloud.stream.binders配置来设定多个Binder,一旦设定了就会发现启动不了。 经过几轮源码调试,终于发现了问题所在。
  1. Dubbo中的DubboServiceRegistrationApplicationContextInitializer类通过ApplicationContextInitializer方式来注入ApplicationContext应用上下文到SpringCloudRegistryFactory中。 spring-cloud-starter-dubbo-2.2.5.RELEASE.jar!\META-INF\spring.factories
  2. Spring Cloud项目启动,实例化各种Bean......(包括了DiscoveryClient)
  3. 在Spring Cloud Stream在处理自定义的Binder配置时,会为其特定的environment配置独立一个ApplicationContext应用上下文(这个有点特殊,时间原因,没有细究),然后会触发ApplicationContextInitializer,Dubbo中的DubboServiceRegistrationApplicationContextInitializer类就获取到了这个特殊的ApplicationContext应用上下文(这个是获取不到实例化好的Bean的)。
  4. SpringCloudRegistryFactory然后在注册Dubbo服务时,使用上一步获取到的ApplicationContext来getBean(DiscoveryClient.class),那自然就报错了。
  • 解决方案 针对上面的情况的话,大体思路是有另外一个Bean通过ApplicationContextAware注入最完整的ApplicationContext应用上下文,然后自己再定义一个新的MyDubboServiceRegistrationApplicationContextInitializer类,实际注入到SpringCloudRegistryFactory的ApplicationContext应用上下文就用之前ApplicationContextAware注入的到那个。 当然要注意验证MyDubboServiceRegistrationApplicationContextInitializer的加载顺序必须在Dubbo中的DubboServiceRegistrationApplicationContextInitializer后面才行。
  • 代码实现
package org.zze0;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Optional;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static Optional<ApplicationContext> tryGetApplicationContext() {
        return Optional.ofNullable(applicationContext);
    }
}
package org.zze0;

import com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;

@Order
public class MyDubboServiceRegistrationApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        SpringUtils.tryGetApplicationContext()
                .filter(context -> context instanceof ConfigurableApplicationContext)
                .map(context -> (ConfigurableApplicationContext) context)
                .ifPresent(SpringCloudRegistryFactory::setApplicationContext);
    }
}

spring.factories:

org.springframework.context.ApplicationContextInitializer=\
  org.zze0.MyDubboServiceRegistrationApplicationContextInitializer
  • 最后的话 个人拙见,实测顺利通过。如果不对,请指正,谢谢哈!

@fangjian0423 @laiweijia @tyq0010 @gaochuanneu @mercyblitz 挖个坟,我有遇到上面说的问题,场景类似,但没有豆子的冲突。下面说下我的情况。

  • 异常

Dubbo自动关停自我疏 11:39:12.242 [main] INFO oadrtAbstractServer - [,73] - [DUBBO] 启动NettyServer bind /0.0.0.0:20880, export /10.10.10.2:20880, dubbo version: 2.7.8,当前主机:10.10.10.2 11:39:12.264 [main] INFO cacdsDubboMetadataServiceExporter - [unexport,106] - Dubbo 服务[] 已取消导出。 11:39:12.266 [main] INFO oadrsAbstractRegistryFactory - [destroyAll,81] - [DUBBO] 关闭所有注册中心 [],dubbo 版本:2.7.8,当前主机:10.10.10.2 11:39:12.266 [main] INF0B [destroy,615] - [DUBBO]关闭dubbo服务器:/10.10.10.2:20880,dubbo版本:2.7.8,当前主机:10.10.10.2 11:39:12.267 [main] INFO oadrtAbstractServer - [close,128] - [DUBBO] 关闭 NettyServer 绑定 /0.0.0.0:20880,导出 /10.10.10.2:20880,dubbo 版本:2.7.8,当前主机:10.10 10.2 然后抛出异常: org.springframework.beans.factory.NoSuchBeanDefinitionException: Noqualifying bean of type 'org.springframework.cloud.client.discovery.DiscoveryClient' available

  • 环境

spring-cloud-stream-binder-kafka:3.0.8.RELEASE spring-cloud-starter-dubbo:2.2.5.RELEASE spring-cloud-dependencies:Hoxton.SR8 spring-cloud-alibaba-dependencies:2.2.5.RELEASE nacos 客户端:2.0.0

  • 问题分析 共性是用了spring.cloud.stream.binders配置来设置一些,如果设置了就会发现启动不了。 经过几次循环源调试,终于发现了问题所在。
  1. Dubbo中的DubboServiceRegistrationApplicationContextInitializer类通过ApplicationContextInitializer方式来注入ApplicationContext应用上下文到SpringCloudRegistryFactory中。 spring-cloud-starter-dubbo-2.2.5.RELEASE.jar!\META-INF\spring.factories
  2. Spring Cloud 项目启动,实例化各种Bean......(包括了DiscoveryClient)
  3. 在Spring Cloud Stream在处理自定义的Binder配置时,会自己特定的这个环境配置独立一个ApplicationContext应用上下文(有点特殊,时间原因,没有细究),然后会触发ApplicationContextInitializer,Dubbo中的DubboServiceRegistrationApplicationContextInitializer类就获取到了特殊的ApplicationContext应用上下文(这个是获取不到实例化好的Bean的)。
  4. SpringCloudRegistryFactory然后在注册Dubbo服务时,使用上一步获取到的ApplicationContext来getBean(DiscoveryClient.class),那自然就报错了。
  • 解决方案 针对上面的情况,大体思路是另外一个Bean通过ApplicationContextAware注入最完整的应用上下文,然后定义一个新MyDubboServiceRegistrationApplicationContextInitializer类,实际注入到SpringCloudRegistryFactory的ApplicationContext应用上下文就用之前再ApplicationContextAware注入的那个。 当然注意验证MyDubboServiceRegistrationApplicationContextInitializer的加载顺序必须在Dubbo中的DubboServiceRegistrationApplicationContextInitializer进去才行。
  • 代码实现
包 org.zze0 ;

导入 org.springframework.beans.BeansException;
导入 org.springframework.context.ApplicationContext;
导入 org.springframework.context.ApplicationContextAware;
导入 org.springframework.stereotype.Component;
导入 java.util.Optional ;

@Component
公共 类 SpringUtils 实现了 ApplicationContextAware {

    私有 静态 ApplicationContext applicationContext =  null ;

    @覆盖
    公共 空隙 setApplicationContext(ApplicationContext中 的applicationContext)抛出 BeansException {
         SpringUtils 。应用上下文 =应用上下文;
    }

    公共 静态 可选< ApplicationContext >  tryGetApplicationContext () {
        返回 可选。ofNullable(applicationContext);
    }
}
包 org.zze0 ;

导入 com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
导入 org.springframework.context.ApplicationContextInitializer;
导入 org.springframework.context.ConfigurableApplicationContext;
导入 org.springframework.core.annotation.Order;

@Order
公共 类 MyDubboServiceRegistrationApplicationContextInitializer 实现 ApplicationContextInitializer< ConfigurableApplicationContext > {
     @Override 
    public  void  initialize ( ConfigurableApplicationContext  applicationContext ) {
         SpringUtils . tryGetApplicationContext()
                .filter(context - > ConfigurableApplicationContext 的上下文实例 )
                .map(context - > ( ConfigurableApplicationContext ) 上下文)
                .ifPresent( SpringCloudRegistryFactory :: setApplicationContext);
    }
}

spring.factories:

org.springframework.context.ApplicationContextInitializer=\ 
  org.zze0.MyDubboServiceRegistrationApplicationContextInitializer
  • 的求最后话教育 个人拙见,实测顺利通过。如果不对,请指正,谢谢哈!

老哥 你测试通过了? 我按照你的方法,没有测试成功,主要是你上面说的,这个自定义的类要在DubboServiceRegistrationApplicationContextInitializer这个类的后面加载,但是我一直都是自定义的在首先加载的,我不太清楚是不是这个原因,请老哥回复一下

Zze0 commented 3 years ago

老哥 你测试通过了? 我按照你的方法,没有测试成功,主要是你上面说的,这个自定义的类要在DubboServiceRegistrationApplicationContextInitializer这个类的后面加载,但是我一直都是自定义的在首先加载的,我不太清楚是不是这个原因,请老哥回复一下

@lwk595ww

确实,需要保证你自定义的MyDubboServiceRegistrationApplicationContextInitializer的加载顺序必须在Dubbo中的DubboServiceRegistrationApplicationContextInitializer后面执行才行。这个通过DEBUG是可以试出来的。如果是你自定义的顺序是在其之前的话,那就不对了。

其实看到上述提到的源码也看到了DubboServiceRegistrationApplicationContextInitializer类是没有定义Order优先级的,那么他在Spring内部默认优先级就是最低的(也就是等价于@Order(Integer.MAX_VALUE)),所以在这个时候就很难保证我们自定义的Bean一定能排在它之后。

至于我那边测试是通过的原因,可能是因为我是自己把这个类放到自定义的Spring Boot Starter项目中,然后再引入到自己的项目里。(这里要注意下依赖包加载优先级问题,我记得Maven加载顺序好像默认以groupId+artifactId的级别深度,深度越浅那么优先级就越高,如果是想自己的自定义依赖包里面的MyDubboServiceRegistrationApplicationContextInitializer类是最后加载的话,就需要把groupId写深点。)你可以试试我的这种方式。

那么有没有另外一种办法呢?据我目前了解到的内容和查看源码后的感想来看,通过调整DubboServiceRegistrationApplicationContextInitializer类实例化顺序在自定义的之前几乎是做不到的,因为无论是使用@Order注解还是Ordered接口都是需要修改代码才能达到的。我也尝试过使用AOP切面去处理,结果发现其实例化ApplicationContextInitializer的时候并没有使用代理模式生成代理对象,所以基本该方案也做不了。

所以如果实在没有办法,你可以尝试直接复制DubboServiceRegistrationApplicationContextInitializer类的源码到自己本地项目里面,包名和阿里巴巴的包名一致,相当于覆盖依赖包里面的类。因为遇到同全限定名的类时,类加载器默认会优先加载使用本地项目的类。如下:

package com.alibaba.cloud.dubbo.context;

import com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;

public class DubboServiceRegistrationApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        SpringUtils.tryGetApplicationContext()
                .filter(context -> context instanceof ConfigurableApplicationContext)
                .map(context -> (ConfigurableApplicationContext) context)
                .ifPresent(SpringCloudRegistryFactory::setApplicationContext);
    }
}

哦,对了,具体触发ApplicationContextInitializer的源码在这儿(里面也有排序的代码),有兴趣可以自己跟下:org.springframework.web.servlet.FrameworkServlet#applyInitializers