spring cloud 使用 @EnableDiscoveryClient 关闭应用时报 factory.BeanCreationNotAllowedException

当Eureka客户端在Spring Cloud应用中使用Refresh特性时,可能会遇到BeanCreationNotAllowedException异常,导致应用无法正常注销。此问题在Spring Boot 2.0.4和1.5.14版本中尤为明显,其根本原因是RefreshScope与DiscoveryClient的交互冲突。禁用spring.cloud.refresh.enabled特性或调整关闭流程可以避免该异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'eurekaInstanceConfigBean': 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)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:818)
	at org.springframework.beans.factory.support.ConstructorResolver.resolvePreparedArguments(ConstructorResolver.java:767)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1247)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$1(AbstractBeanFactory.java:353)
	at org.springframework.cloud.context.scope.GenericScope$BeanLifecycleWrapper.getBean(GenericScope.java:390)
	at org.springframework.cloud.context.scope.GenericScope.get(GenericScope.java:184)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:350)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:672)
	at com.netflix.appinfo.ApplicationInfoManager$$EnhancerBySpringCGLIB$$59c481a2.unregisterStatusChangeListener(<generated>)
	at com.netflix.discovery.DiscoveryClient.shutdown(DiscoveryClient.java:891)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeDestroyMethods(InitDestroyAnnotationBeanPostProcessor.java:324)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction(InitDestroyAnnotationBeanPostProcessor.java:156)
	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:240)
	at org.springframework.beans.factory.support.DisposableBeanAdapter.run(DisposableBeanAdapter.java:233)
	at org.springframework.cloud.context.scope.GenericScope$BeanLifecycleWrapper.destroy(GenericScope.java:404)
	at org.springframework.cloud.context.scope.GenericScope.destroy(GenericScope.java:139)
	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:256)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:571)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:543)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:954)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:504)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:961)
	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1041)
	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1017)
	at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:967)
	at org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar$SpringApplicationAdmin.shutdown(SpringApplicationAdminMXBeanRegistrar.java:133)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
	at com.sun.jmx.mbeanserver.ConvertingMethod.invokeWithOpenReturn(ConvertingMethod.java:193)
	at com.sun.jmx.mbeanserver.ConvertingMethod.invokeWithOpenReturn(ConvertingMethod.java:175)
	at com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(MXBeanIntrospector.java:117)
	at com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(MXBeanIntrospector.java:54)
	at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:237)
	at com.sun.jmx.mbeanserver.PerInterface.invoke(PerInterface.java:138)
	at com.sun.jmx.mbeanserver.MBeanSupport.invoke(MBeanSupport.java:252)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
	at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
	at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
	at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
	at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

解决办法:在 src/main/resources/application.properties 中配置 spring.cloud.refresh.enabled=false 关闭刷新特性

https://github.com/spring-cloud/spring-cloud-netflix/issues/3140

问题原因:

https://github.com/spring-cloud/spring-cloud-netflix/issues/3174

 

brenuart commented on 3 Sep

 

BeanCreationNotAllowedException is thrown during application context shutdown by the DiscoveryClient.

This is issue has already been reported since long in different scenarios and different (apparent) causes. There have been many attempts at solving the issue so far, but unfortunately, although each attempt solved one cause, there are still cases where the exception is thrown.

A short summary first before a more detailed description below:

  • the problem occurs during shutdown of the application after the eureka client has successfully registered with the registry
  • the problem does NOT occur if the SpringCloud RefreshScope feature is disabled via spring.cloud.refresh.enabled=false. RefreshScope is the root cause in this scenario.
  • it can be easily reproduced with Boot 2.0.4 or 1.5.14 (ie Spring Cloud Edgware.SR4 or Finchley.SR1)
  • the exception prevents the client from being unregistered from the registry during shutdon

The problem can be easily reproduced with a simple Spring Initilizr bootstrap project with only the Eureka Discovery dependency selected. This is reproductible with Boot 2.0.4 or 1.5.14 (ie Spring Cloud Edgware.SR4 or Finchley.SR1).
You need a running Eureka server so the sample client can be successfully registered. Start the application with the standard configuration (nothing special needed here) and make sure it is registered with the Eureka registry. Then stop the application properly so the shutdown sequence is executed (Ctrl-C should do it). You should see the following log lines during the shutdown:

2018-09-03 13:50:26.443  INFO 9494 --- [on(2)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2018-09-03 13:50:26.443  INFO 9494 --- [on(2)-127.0.0.1] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a362b6b: startup date [Mon Sep 03 13:49:45 CEST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@5c30a9b0
2018-09-03 13:50:26.444  INFO 9494 --- [on(2)-127.0.0.1] o.s.c.n.e.s.EurekaServiceRegistry        : Unregistering application unknown with eureka with status DOWN
2018-09-03 13:50:26.444  WARN 9494 --- [on(2)-127.0.0.1] com.netflix.discovery.DiscoveryClient    : Saw local status change event StatusChangeEvent [timestamp=1535975426444, current=DOWN, previous=UP]
2018-09-03 13:50:26.444  INFO 9494 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_UNKNOWN/macfury.lan: registering service...
2018-09-03 13:50:26.445  INFO 9494 --- [on(2)-127.0.0.1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 0
2018-09-03 13:50:26.446  INFO 9494 --- [on(2)-127.0.0.1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2018-09-03 13:50:26.446  INFO 9494 --- [on(2)-127.0.0.1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans
2018-09-03 13:50:26.448  INFO 9494 --- [on(2)-127.0.0.1] com.netflix.discovery.DiscoveryClient    : Shutting down DiscoveryClient ...
2018-09-03 13:50:26.450  WARN 9494 --- [on(2)-127.0.0.1] .s.c.a.CommonAnnotationBeanPostProcessor : Invocation of destroy method failed on bean with name 'scopedTarget.eurekaClient': org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'eurekaInstanceConfigBean': 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!)
2018-09-03 13:50:26.455  INFO 9494 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_UNKNOWN/macfury.lan - registration status: 204
2018-09-03 13:50:26.505  INFO 9494 --- [on(2)-127.0.0.1] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

As you can see in the last few lines, a BeanCreationNotAllowedException exception is thrown when destroying the bean scopedTarget.eurekaClient. The remaining part of the message gives us some hints about what's going on:

Error creating bean with name 'eurekaInstanceConfigBean': 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!)

The DiscoveryClient#shutdown() method starts with the following statements:

(1)    public synchronized void shutdown() {
(2)        if (isShutdown.compareAndSet(false, true)) {
(3)            logger.info("Shutting down DiscoveryClient ...");
(4)
(5)            if (statusChangeListener != null && applicationInfoManager != null) {
(6)                applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
(7)            }

The exception is thrown when the execution hits line (6).
You should remember both the DiscoveryClient and ApplicationInfoManager are RefreshScope beans (unless the Refresh feature is disabled with spring.cloud.refresh.enabled=false, it is enabled by default). Consequence is the applicationInfoManager is a refresh-scope proxy whose target must be resolved when the unregisterStatusChangeListener is invoked - this is done via a getBean(..) call on the application context.
The shutdown method is invoked by the application context during its shutdown procedure. At this point the underlying BeanFactory is in a closing state and actively refuses any getBean(...) call made by other components, throwing BeanCreationNotAllowedException at any attempt.

Let's recap:

  • DiscoveryClient.shutdown() is invoked during the application context shutdown/close process
  • DiscoveryClient needs to unregister from the ApplicationInfoManager
  • applicationInfoManager is refresh-scoped, its target must be resolved for every method invocation
  • the resolution fails with a BeanCreationNotAllowedException because the BeanFactory is in closing state.

At the end, we do actually request a bean from a BeanFactory in a destroy method implementation!, which is, as per the exception message, not allowed.

The problem does NOT appear if the refresh feature is disabled with spring.cloud.refresh.enabled=false.

 

### 回答1: 这是一个Spring框架的异常,意味着在创建bean出现了问题。可能是因为尝试在应用程序上下文之外创建bean,或者在bean的生命周期中尝试修改bean的状态。建议检查代码并确保正确地使用Spring框架。 ### 回答2: org.springframework.beans.factory.beancreationnotallowedexception是一个Spring Framework中的异常类,它表示Bean创建不允许的异常。 这个异常通常发生在以下情况下: 1.使用Spring的bean定义文件配置Bean,可能会出现错误的配置或配置冲突的情况,导致无法创建Bean实例。 2. 当尝试在Spring容器中手动创建和注册Bean实例,可能会由于容器的限制导致无法创建Bean。 解决该异常的方法有以下几种: 1. 检查bean定义文件的配置是否正确,特别是关于bean的依赖和引用的配置,可能存在配置冲突或依赖缺失的情况。 2. 确保所有的bean在容器中都有正确的引用,如果有使用@Autowired或@Resource这样的注解进行自动注入,确保注入的对象存在并符合条件。 3. 检查容器中的bean创建策略,Spring容器有一些策略限制是否允许手动创建Bean,可能需要根据具体的容器设置进行调整。 4. 如果使用的是Spring的注解配置(如@Component和@Configuration),确保注解的使用正确,并且所有的依赖都正确注入。 总的来说,org.springframework.beans.factory.beancreationnotallowedexception异常表示Bean创建不允许的异常,它可能由于配置错误、依赖缺失或容器策略限制等原因造成。通过检查和修复相关配置、依赖以及容器设置,可以解决该异常。 ### 回答3: org.springframework.beans.factory.BeanCreationNotAllowedExceptionSpring框架中的一个异常,表示禁止创建Bean实例。 在Spring框架中,Bean的创建和初始化是由容器负责的。当遇到 BeanCreationNotAllowedException 异常,通常是因为某些原因导致容器禁止创建该Bean实例。 常见的原因有以下几种: 1. 当前的Bean已经在容器中存在,并且Scope设置为singleton。在singleton模式下,Bean只能创建一个实例,如果尝试再次创建,就会抛出异常。 2. 在Bean的定义中,可能指定了abstract属性为true。abstract属性表示该Bean是一个抽象的定义,不可被实例化。 3. 存在循环依赖的情况。当Bean A依赖Bean B,而Bean B又依赖Bean A,会导致死循环,从而容器禁止创建Bean实例。 解决这个异常的方法有以下几种: 1. 检查容器中是否已经存在相同的Bean实例,确保singleton模式的Bean只能创建一次。 2. 将abstract属性设置为false,确保Bean的定义可被实例化。 3. 检查是否存在循环依赖,如果是,可以考虑通过重新设计Bean之间的依赖关系来解决。 总之,org.springframework.beans.factory.BeanCreationNotAllowedException 异常是由Spring框架抛出的,表示禁止创建Bean实例。通过检查Bean的定义、依赖关系和容器的配置,可以解决这个异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值