Mark @FeignClient beans as primary.

When fallback beans are created, there was no longer a unique bean of the feign interface which caused autowire problems.

fixes gh-899
This commit is contained in:
Spencer Gibb
2016-03-16 17:01:45 -06:00
parent b9a6876d00
commit 08f7076f6e
3 changed files with 24 additions and 9 deletions

View File

@@ -789,7 +789,7 @@ In the `@FeignClient` annotation the String value ("stores" above) is
an arbitrary client name, which is used to create a Ribbon load
balancer (see <<spring-cloud-ribbon,below for details of Ribbon
support>>). You can also specify a URL using the `url` attribute
(absolute value or just a hostname).
(absolute value or just a hostname). The name of the bean in the application context is the fully qualified name of the interface. An alias is also created which is the 'name' attribute plus 'FeignClient'. For the example above, `@Qualifier("storesFeignClient")` could be used to reference the bean.
The Ribbon client above will want to discover the physical addresses
for the "stores" service. If your application is a Eureka client then

View File

@@ -171,14 +171,18 @@ public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
.genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("name", getServiceId(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias = name + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
beanDefinition.setPrimary(true);
BeanDefinitionHolder holder = new BeanDefinitionHolder(
definition.getBeanDefinition(), className);
beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
@@ -189,7 +193,7 @@ public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
}
}
private String getServiceId(Map<String, Object> attributes) {
private String getName(Map<String, Object> attributes) {
String name = (String) attributes.get("serviceId");
if (!StringUtils.hasText(name)) {
name = (String) attributes.get("name");

View File

@@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
@@ -115,6 +116,10 @@ public class FeignClientTests {
@Autowired
HystrixClient hystrixClient;
@Autowired
@Qualifier("localapp3FeignClient")
HystrixClient namedHystrixClient;
protected enum Arg {
A, B;
@@ -270,6 +275,12 @@ public class FeignClientTests {
})
protected static class Application {
// needs to be in parent context to test multiple HystrixClient beans
@Bean
public HystrixClientFallback hystrixClientFallback() {
return new HystrixClientFallback();
}
@Bean
FeignFormatterRegistrar feignFormatterRegistrar() {
return new FeignFormatterRegistrar() {
@@ -543,6 +554,11 @@ public class FeignClientTests {
assertEquals("message was wrong", "fallbackfuture", hello.getMessage());
}
@Test
public void namedFeignClientWorks() {
assertNotNull("namedHystrixClient was null", this.namedHystrixClient);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@@ -556,11 +572,6 @@ public class FeignClientTests {
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public HystrixClientFallback hystrixClientFallback() {
return new HystrixClientFallback();
}
}
// Load balancer with fixed server list for "local" pointing to localhost