Error creating bean with name 'eurekaAutoServiceRegistration': Singleton bean creation not allowed解决

2019-06-24 18:41:47.106  INFO 3025 --- [       Thread-6] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2cd2c8fe: startup date [Mon Jun 24 18:34:12 CST 2019]; parent: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@382db087
2019-06-24 18:41:47.107  WARN 3025 --- [       Thread-6] s.c.a.AnnotationConfigApplicationContext : Exception thrown from ApplicationListener handling ContextClosedEvent

org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'eurekaAutoServiceRegistration': 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:216)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.getTargetBean(ApplicationListenerMethodAdapter.java:283)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:253)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:177)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:140)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:991)
        at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:958)
        at org.springframework.cloud.context.named.NamedContextFactory.destroy(NamedContextFactory.java:76)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:272)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
        at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.destroySingletons(FactoryBeanRegistrySupport.java:230)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1032)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1008)
        at org.springframework.context.support.AbstractApplicationContext$2.run(AbstractApplicationContext.java:929)

并不是微服务启动的时候报错,是微服务已经起来了,运行了一段时间就挂了,日志见上。大致意思应该是我的服务没办法注册到Eureka中心。

GitHub有一个大神 @crmky 给出了答案,传送门:
https://github.com/spring-cloud/spring-cloud-netflix/issues/1952

解决方法:

新建一个类,配置一下:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class FeignBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (containsBeanDefinition(beanFactory, "feignContext", "eurekaAutoServiceRegistration")) {
            BeanDefinition bd = beanFactory.getBeanDefinition("feignContext");
            bd.setDependsOn("eurekaAutoServiceRegistration");
        }
    }

    private boolean containsBeanDefinition(ConfigurableListableBeanFactory beanFactory, String... beans) {
        return Arrays.stream(beans).allMatch(b -> beanFactory.containsBeanDefinition(b));
    }
}

以下是原话:

The root cause is when closing ApplicationContext, it will destroy all singleton bean, eurekaAutoServiceRegistration is destroyed first, then feignContext. When destroy feignContext, it will close the ApplicationContext associated with each FeignClient. Since eurekaAutoServiceRegistration listen on ContextClosedEvent, those events will be sent to that bean. Unfortunately because it has been destroyed, so we got the above exception (try to create bean in destruction).

根本原因是当关闭ApplicationContext时,它会销毁所有单例bean,首先销毁eurekaAutoServiceRegistration,然后是feignContext。当破坏feignContext时,它将关闭与每个FeignClient关联的ApplicationContext。由于eurekaAutoServiceRegistration侦听ContextClosedEvent,因此这些事件将被发送到该bean。不幸的是因为它已被破坏,所以我们得到了上述异常(尝试在破坏中创建bean)。

@EventListener(ContextClosedEvent.class)
	public void onApplicationEvent(ContextClosedEvent event) {
		// register in case meta data changed
		stop();
	}

后面crmky 与 spencergibb 的对话大概知道

spencergibb 修复了一个版本但是 crmky 试了一下还是有问题:

crmky:

I tried the latest snapshot version, still see the same stack trace without my workaround.

I think fix within onApplicationEvent method will not work. The problem is EurekaAutoServiceRegistration bean had been destroyed, then it received ContextClosedEvent for the ApplicationContext associated with FeignClients. BeanFactory try to create that bean again and triggered that exception.

Here are the whole steps:

SpringApplication level ApplicationContext shutdown
EurekaAutoServiceRegistration.onApplicationEvent get called and deregister Eureka instance.
EurekaAutoServiceRegistration bean is destroyed. (Because InetUtils and EurekaServiceRegistry are destroyed)
Destroying FeignContext.
FeignContext will destroy ApplicationContext associated with each FeignClient.
ApplicationContext try to notify EurekaAutoServiceRegistration.onApplicationEvent, because of EventListener annotation. But that bean is destroyed, so it try to re-create it.
Not the right time to create bean (shutdown), exception thrown.

我尝试了最新的快照版本,仍然看到相同的堆栈跟踪没有我的解决方法。 我认为onApplicationEvent方法中的修复不起作用。问题是EurekaAutoServiceRegistration bean已经被销毁,然后它收到了与FeignClients关联的ApplicationContext的ContextClosedEvent。 BeanFactory尝试再次创建该bean并触发该异常。 以下是整个步骤: SpringApplication级别ApplicationContext关闭 EurekaAutoServiceRegistration.onApplicationEvent被调用并取消注册Eureka实例。 EurekaAutoServiceRegistration bean被销毁。 (因为InetUtils和EurekaServiceRegistry被销毁) 摧毁FeignContext。 FeignContext将销毁与每个FeignClient关联的ApplicationContext。 由于EventListener注释,ApplicationContext尝试通知EurekaAutoServiceRegistration.onApplicationEvent。但是那个bean被破坏了,所以它试图重新创建它。 不是创建bean(shutdown)的正确时间,抛出异常。

就是说这个问题 Spring Cloud Edgware.SR1. 版本是会存在这个问题。

最后修复的版本是这个:https://github.com/spring-cloud/spring-cloud-netflix/commit/12583fd0c25638f95c14973d921ca28cdcd17df5

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醋酸菌HaC

请我喝杯奶茶吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值