最近在练习Eureka,在搭建环境的时候遇到了一点问题,于是记录了下来。
我把Eureka客户端的启动类命名为EurekaClient,一直启动不了,但我把类型改成MyEurekaClient之后,就能启动成功。
为什么启动类名不能是EurekaClient,带着疑问,一步一步debug,慢慢揭开了迷雾。
原文地址:https://blog.csdn.net/ShrMus/article/details/97048158
先看看Spring Boot 2.x版本报错信息
在Spring启动加载BeanDefinition的时候
调用栈
AbstractApplicationContext#refresh()
invokeBeanFactoryPostProcessors(beanFactory);
ConfigurationClassPostProcessor#processConfigBeanDefinitions(BeanDefinitionRegistry registry)
this.reader.loadBeanDefinitions(configClasses);
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions(Set<ConfigurationClass> configurationModel)
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
注意看上图我选中的那一行,在加载EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration
这个类的时候,我再执行到下一步,就跳到了AbstractApplicationContext#refresh()中的catch代码块,看来问题就在加载这个类
于是我到EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration去看了一眼
这个类中的eurekaClient方法上有个注解
@Bean(destroyMethod = "shutdown")
这个注解把返回的对象注册到容器,BeanName为方法名
我写的启动类是EurekaClient,已经被注册到Spring容器里了,BeanName是eurekaClient
这下就明白了
再看看Spring Boot 1.x版本报错信息
当Spring执行getBean的时候
调用栈
AbstractApplicationContext#refresh()
finishBeanFactoryInitialization(beanFactory);
AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
beanFactory.preInstantiateSingletons();
DefaultListableBeanFactory#preInstantiateSingletons()
注意看上图我选中的那一行,当前beanName是org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration$EurekaClientConfigurationRefresher
执行getBean后,就跳到了AbstractApplicationContext#refresh()中的catch代码块
于是我到org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration$EurekaClientConfigurationRefresher看了一下
这个类有个com.netflix.discovery.EurekaClient eurekaClient属性需要注入,但是在容器中找不到这个类型的bean,所以这个属性值为null
还有个org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration autoRegistration属性,需要注入
org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration类有个
org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration registration属性
org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration类有个com.netflix.discovery.EurekaClient eurekaClient属性
在实例化org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration类
获取eurekaClient的时候报错
No qualifying bean of type 'com.netflix.discovery.EurekaClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
最终org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration类里没有一个属性
ConstructorResolver#createArgumentArray(String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues,BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,boolean autowiring)
Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName,autowiredBeanNames, converter);
最终抛出异常。