将Springboot 1.x中的Netflix Feign迁移到Springboot 2.x中的OpenFeign

10

我尝试将Springboot 1.x.y (布鲁塞尔-SR12)迁移到2.x.y。我使用FeignClients

我更改了Maven配置:

<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>

so

<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>2.0.0.RELEASE</version>

我更改了所有的导入:

import org.springframework.cloud.netflix.feign.EnableFeignClients;

import org.springframework.cloud.netflix.feign.FeignClient;

为了

import org.springframework.cloud.openfeign.EnableFeignClients;

import org.springframework.cloud.openfeign.FeignClient;

我使用这个接口:
@FeignClient(value = "COMPANY", fallbackFactory = CompanyClientFallbackFactory.class, configuration = FeignConfiguration.class)
public interface CompanyClient extends CompanyApi {
}

当我运行带有Spring上下文的JUnit测试时,现在会出现以下错误(这在Springboot 1.x.y和旧版Netflix包中没有出现):

The bean 'COMPANY.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

完整的跟踪信息:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.postProcessFields(MockitoTestExecutionListener.java:99)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.injectFields(MockitoTestExecutionListener.java:79)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.prepareTestInstance(MockitoTestExecutionListener.java:54)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
...
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'COMPANY.FeignClientSpecification' defined in null: Cannot register bean definition [Generic bean: class [org.springframework.cloud.openfeign.FeignClientSpecification]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'COMPANY.FeignClientSpecification': There is already [Generic bean: class [org.springframework.cloud.openfeign.FeignClientSpecification]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:896)
    at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerClientConfiguration(FeignClientsRegistrar.java:355)
    at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerFeignClients(FeignClientsRegistrar.java:155)
    at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerBeanDefinitions(FeignClientsRegistrar.java:83)
6个回答

20

这是来自Feign文档的解决方案:

If we want to create multiple feign clients with the same name or url so that they would point to the same server but each with a different custom configuration then we have to use contextId attribute of the @FeignClient in order to avoid name collision of these configuration beans.

@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
    //..
}

@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
    //..
}

https://github.com/spring-cloud/spring-cloud-openfeign/pull/90/commits/82fa5181fdd2e23e7414521f468ecea88e17d157


8

可能您有多个具有相同名称属性的@FeignClient定义。


8

如果您意外地有多个使用 @EnableFeignClients 注释的 @Configuration 类,则也会发生此情况。


这对我解决了问题。但我仍然希望在不同的模块中有两个单独的配置。 - FazoM

0

我找到了一个解决方案,但它只是一个权宜之计。请参见@Alessandro Dionisi的回复

application.yml:

spring:
  main:
    allow-bean-definition-overriding: true

是的,这是一个解决方法,但不是一个解决方案,谢谢@AlessandroDionisi。 - Stéphane GRILLON
这绝对是一个解决方法,你应该考虑重命名你的Feign客户端或使用不同的URL将它们分开。 - talipkorkmaz
这种解决方法会导致更复杂的问题,因为它掩盖了与您的Bean相关的问题。 - Ilya Serbis
@Lu55,请查看Alessandro Dionisi的回复。 - Stéphane GRILLON

0

mvn clean package对我解决了这个错误。


-3

考虑重命名其中一个bean或通过设置spring.main.allow-bean-definition-overriding=true来启用覆盖。


你复制/粘贴了我的答案,但这不是解决方案,而是一种变通的方法。 - Stéphane GRILLON

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接