代码的入口FeignClientFactoryBean 这是一个factoryBean 入口方法getObject() 里面调用的是getTarget()方法
<T> T getTarget() {
FeignContext context = this.applicationContext.getBean(FeignContext.class);
Feign.Builder builder = feign(context);
if (!StringUtils.hasText(this.url)) {
if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
}
else {
this.url = this.name;
}
this.url += cleanPath();
return (T) loadBalance(builder, context,
new HardCodedTarget<>(this.type, this.name, this.url));
}
进入loadBalance代码
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
HardCodedTarget<T> target) {
Client client = getOptional(context, Client.class);
if (client != null) {
builder.client(client);
Targeter targeter = get(context, Targeter.class);
return targeter.target(this, builder, context, target);
}
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
可以看到获取client的方法getOptional。 如果有自定义的负载均衡例如
public class LocalLoadBalancerFeignClient extends LoadBalancerFeignClient {
public LocalLoadBalancerFeignClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory, SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
......
return getResponse(request, options, url.replaceFirst(clientName, configUrl).replace("http:",protocol));
}
private Response getResponse(Request request, Request.Options options, String newUrl) throws IOException {
Request newRequest = Request.create(request.httpMethod(),
newUrl, request.headers(), request.body(),
request.charset());
return defaultClient.execute(newRequest, options);
}
}
如果能找到自定义的路由规则,优先走自定义的
@Bean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, @Autowired(required = false) DiscoveryClient discoveryClient) {
return new LocalLoadBalancerFeignClient(new Client.Default(null, null),
cachingFactory, clientFactory);
}
当没有自定义的时候走default的ribbon的负载均衡,生成client。通过ConditionalOnMissingBean来实现,当没有发现本地的client实现的时候就用该默认的client。
@Configuration(proxyBeanMethods = false)
class DefaultFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory,
clientFactory);
}
}