1. 程式人生 > >一次更新 Error creating bean with name 'eurekaAutoServiceRegistration'

一次更新 Error creating bean with name 'eurekaAutoServiceRegistration'

一次服務更新進行升級時

October 18th 2018, 18:05:35.767	[545]: ++ exit 143
October 18th 2018, 18:05:35.610	[545]: 2018-10-18 18:05:35.611  INFO 13 --- [      Thread-10] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
October 18th 2018, 18:05:35.608	[545]: 
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1009)
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033)
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.context.support.AbstractApplicationContext$2.run(AbstractApplicationContext.java:928)
October 18th 2018, 18:05:35.608	[545]: 	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:389)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.cloud.context.named.NamedContextFactory.destroy(NamedContextFactory.java:76)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:994)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:961)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:272)
October 18th 2018, 18:05:35.607	[545]: 	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:250)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:137)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:174)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
October 18th 2018, 18:05:35.606	[545]: 	at org.springframework.context.event.ApplicationListenerMethodAdapter.getTargetBean(ApplicationListenerMethodAdapter.java:280)
October 18th 2018, 18:05:35.605	[545]: 
October 18th 2018, 18:05:35.605	[545]: 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!)
October 18th 2018, 18:05:35.605	[545]: 	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
October 18th 2018, 18:05:35.605	[545]: 	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
October 18th 2018, 18:05:35.605	[545]: 2018-10-18 18:05:35.604  WARN 13 --- [      Thread-10] s.c.a.AnnotationConfigApplicationContext : Exception thrown from ApplicationListener handling ContextClosedEvent
October 18th 2018, 18:05:35.605	[545]: 	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
October 18th 2018, 18:05:35.605	[545]: 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216)
October 18th 2018, 18:05:35.601	[545]: 	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1009)
October 18th 2018, 18:05:35.601	[545]: 	at org.springframework.context.support.AbstractApplicationContext$2.run(AbstractApplicationContext.java:928)
October 18th 2018, 18:05:35.601	[545]: 
October 18th 2018, 18:05:35.601	[545]: 2018-10-18 18:05:35.603  INFO 13 --- [      Thread-10] s.c.a.AnnotationConfigApplicationContext : Closing org.spring
[email protected]
145bce9d: startup date [Thu Oct 18 12:35:30 GMT+08:00 2018]; parent: org.springframework.boot[email protected]50e8e914 October 18th 2018, 18:05:35.601 [545]: at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:272) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968) October 18th 2018, 18:05:35.600 [545]: at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:961) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) October 18th 2018, 18:05:35.600 [545]: at org.springframework.cloud.context.named.NamedContextFactory.destroy(NamedContextFactory.java:76) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) October 18th 2018, 18:05:35.600 [545]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:137) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:994) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383) October 18th 2018, 18:05:35.599 [545]: at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:389) October 18th 2018, 18:05:35.598 [545]: at org.springframework.context.event.ApplicationListenerMethodAdapter.getTargetBean(ApplicationListenerMethodAdapter.java:280) October 18th 2018, 18:05:35.598 [545]: at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) October 18th 2018, 18:05:35.598 [545]: at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) October 18th 2018, 18:05:35.598 [545]: at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:250) October 18th 2018, 18:05:35.598 [545]: at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) October 18th 2018, 18:05:35.598 [545]: at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:174) October 18th 2018, 18:05:35.597 [545]: 2018-10-18 18:05:35.598 WARN 13 --- [ Thread-10] s.c.a.AnnotationConfigApplicationContext : Exception thrown from ApplicationListener handling ContextClosedEvent October 18th 2018, 18:05:35.597 [545]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216) October 18th 2018, 18:05:35.597 [545]: 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!) October 18th 2018, 18:05:35.597 [545]: October 18th 2018, 18:05:35.596 [545]: 2018-10-18 18:05:35.597 INFO 13 --- [ Thread-10] s.c.a.AnnotationConfigApplicationContext : Closing org.spring
[email protected]
1ec4d67e: startup date [Thu Oct 18 15:17:15 GMT+08:00 2018]; parent: org.springframework.boot[email protected]50e8e914

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).

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

根本原因是:當關閉ApplicationContext,會關閉所有的單例:先是eurekaAutoServiceRegistration,然後是feignContext。當關閉feignContext時,會關閉與每個FeignClient關聯的ApplicationContext,因為eurekaAutoServiceRegistration監聽ContextClosedEvent,ContextClosedEvent的所有事件將會被髮送到那個bean上,因為它已經被關閉了,所以會出現上面異常。

Found a workaround. Also added more details about the root cause.

When ApplicationContext shutdown, it will destroy all disposable beans (and beans depend on them). In this case:

FeignContext implements DisposableBean interface InetUtils implements AutoCloseable interface EurekaServiceRegistry has a public close method So they are all considered as disposable beans. Since EurekaAutoServiceRegistration depends on InetUtils and EurekaServiceRegistry beans, so if either bean is destroyed, EurekaAutoServiceRegistration will be destroyed. Destroy follow First In, Last Out order. Usually application code will not depends on InetUtils or EurekaServiceRegistry, but they depends on FeignClient interfaces. That means FeignContext usually get instituted before InetUtils and EurekaServiceRegistry, so it will be destroyed after them:

InetUtils or EurekaServiceRegistry to be destroyed. Destroy EurekaAutoServiceRegistration first. Destroy InetUtils and EurekaServiceRegistry. Destroy FeignContext which will shutdown all ApplicationContext associated with FeignClients. EurekaAutoServiceRegistration listen on ContextClosedEvent but it has been destroyed. ApplicationContext will try to create it again, got exception. Workaround

Make sure InetUtils and EurekaServiceRegistry are instituted before FeignContext. So the sequence become:

Destroy FeignContext which will shutdown all ApplicationContext associated with FeignClients. EurekaAutoServiceRegistration listen on ContextClosedEvent and processed those events. InetUtils or EurekaServiceRegistry to be destroyed. Destroy EurekaAutoServiceRegistration first. Destroy InetUtils and EurekaServiceRegistry. There are several ways to do that. The recommended solution is implement a BeanFactoryPostProcessor:

一個 解決方案:

@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));
    }
}

這個問題還有更好的解決方案 上述的解決方案 貌似只是讓異常不再丟擲來 有其他解決方案 可以留言評論 QQ: 986359351