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