|
|
@ -16,14 +16,17 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.cloud.netflix.feign; |
|
|
|
package org.springframework.cloud.netflix.feign; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
import lombok.Data; |
|
|
|
import lombok.Data; |
|
|
|
import lombok.EqualsAndHashCode; |
|
|
|
import lombok.EqualsAndHashCode; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.BeansException; |
|
|
|
import org.springframework.beans.factory.FactoryBean; |
|
|
|
import org.springframework.beans.factory.FactoryBean; |
|
|
|
import org.springframework.beans.factory.InitializingBean; |
|
|
|
import org.springframework.beans.factory.InitializingBean; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
|
|
|
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
|
|
|
|
import org.springframework.context.ApplicationContextAware; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
@ -37,7 +40,6 @@ import feign.Retryer; |
|
|
|
import feign.codec.Decoder; |
|
|
|
import feign.codec.Decoder; |
|
|
|
import feign.codec.Encoder; |
|
|
|
import feign.codec.Encoder; |
|
|
|
import feign.codec.ErrorDecoder; |
|
|
|
import feign.codec.ErrorDecoder; |
|
|
|
import feign.ribbon.LoadBalancingTarget; |
|
|
|
|
|
|
|
import feign.slf4j.Slf4jLogger; |
|
|
|
import feign.slf4j.Slf4jLogger; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -45,7 +47,7 @@ import feign.slf4j.Slf4jLogger; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Data |
|
|
|
@Data |
|
|
|
@EqualsAndHashCode(callSuper = false) |
|
|
|
@EqualsAndHashCode(callSuper = false) |
|
|
|
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean { |
|
|
|
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware { |
|
|
|
|
|
|
|
|
|
|
|
private Class<?> type; |
|
|
|
private Class<?> type; |
|
|
|
|
|
|
|
|
|
|
@ -53,35 +55,7 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean { |
|
|
|
|
|
|
|
|
|
|
|
private String url; |
|
|
|
private String url; |
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
private ApplicationContext context; |
|
|
|
private Decoder decoder; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
|
|
private Encoder encoder; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
|
|
private Logger logger; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
|
|
private Contract contract; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private Logger.Level logLevel; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private Retryer retryer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private ErrorDecoder errorDecoder; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private Request.Options options; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private Client ribbonClient; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
|
|
|
private List<RequestInterceptor> requestInterceptors; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void afterPropertiesSet() throws Exception { |
|
|
|
public void afterPropertiesSet() throws Exception { |
|
|
@ -91,40 +65,67 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void setApplicationContext(ApplicationContext context) throws BeansException { |
|
|
|
|
|
|
|
this.context = context; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected Feign.Builder feign() { |
|
|
|
protected Feign.Builder feign() { |
|
|
|
|
|
|
|
// @formatter:off
|
|
|
|
Feign.Builder builder = Feign.builder() |
|
|
|
Feign.Builder builder = Feign.builder() |
|
|
|
// required values
|
|
|
|
// required values
|
|
|
|
.logger(this.logger).encoder(this.encoder).decoder(this.decoder) |
|
|
|
.logger(get(Logger.class)) |
|
|
|
.contract(this.contract); |
|
|
|
.encoder(get(Encoder.class)) |
|
|
|
|
|
|
|
.decoder(get(Decoder.class)) |
|
|
|
|
|
|
|
.contract(get(Contract.class)); |
|
|
|
|
|
|
|
// @formatter:on
|
|
|
|
|
|
|
|
|
|
|
|
// optional values
|
|
|
|
// optional values
|
|
|
|
if (this.logLevel != null) { |
|
|
|
Logger.Level level = getOptional(Logger.Level.class); |
|
|
|
builder.logLevel(this.logLevel); |
|
|
|
if (level != null) { |
|
|
|
|
|
|
|
builder.logLevel(level); |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.retryer != null) { |
|
|
|
Retryer retryer = getOptional(Retryer.class); |
|
|
|
builder.retryer(this.retryer); |
|
|
|
if (retryer != null) { |
|
|
|
|
|
|
|
builder.retryer(retryer); |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.errorDecoder != null) { |
|
|
|
ErrorDecoder errorDecoder = getOptional(ErrorDecoder.class); |
|
|
|
builder.errorDecoder(this.errorDecoder); |
|
|
|
if (errorDecoder != null) { |
|
|
|
|
|
|
|
builder.errorDecoder(errorDecoder); |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.options != null) { |
|
|
|
Request.Options options = getOptional(Request.Options.class); |
|
|
|
builder.options(this.options); |
|
|
|
if (options != null) { |
|
|
|
|
|
|
|
builder.options(options); |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.requestInterceptors != null) { |
|
|
|
Map<String, RequestInterceptor> requestInterceptors = this.context.getBeansOfType(RequestInterceptor.class); |
|
|
|
builder.requestInterceptors(this.requestInterceptors); |
|
|
|
if (requestInterceptors != null) { |
|
|
|
|
|
|
|
builder.requestInterceptors(requestInterceptors.values()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return builder; |
|
|
|
return builder; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected <T> T get(Class<T> type) { |
|
|
|
|
|
|
|
return this.context.getBean(type); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected <T> T getOptional(Class<T> type) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
return this.context.getBean(type); |
|
|
|
|
|
|
|
} catch (NoSuchBeanDefinitionException e) { |
|
|
|
|
|
|
|
//ignore
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) { |
|
|
|
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) { |
|
|
|
builder.logger(new Slf4jLogger(type)); // TODO: how to have choice here?
|
|
|
|
builder.logger(new Slf4jLogger(type)); // TODO: how to have choice here?
|
|
|
|
if (this.ribbonClient != null) { |
|
|
|
Client client = getOptional(Client.class); |
|
|
|
return builder.client(this.ribbonClient).target(type, schemeName); |
|
|
|
if (client != null) { |
|
|
|
} |
|
|
|
return builder.client(client).target(type, schemeName); |
|
|
|
else { |
|
|
|
|
|
|
|
return builder.target(LoadBalancingTarget.create(type, schemeName)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-ribbon?"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|