天生我材比有用,千金散尽还复来!
通过接口模板形式的调用,简化调用流程,使用动态代理http发送请求,默认集成ribbon进行负载均衡;
简单使用
配置调用接口
public interface OrderService {
@GetMapping("/orders")
String orders();
@PostMapping("/order")
int insert(OrderDto dto);
}
@FeignClient("order-service")
public interface OrderServiceFeignClient extends OrderService{
}
客户端配置调用
//首先加入api依赖,然后扫描.
@EnableFeignClients(basePackages = "com.xx.xx.clients")
//注入调用
@Autowired
OrderServiceFeignClient orderServiceFeignClient;
@GetMapping("/test")
public String test(){
return orderServiceFeignClient.getAllOrder();
}
其他配置
# 配置指定服务的提供者的地址列表
order-service.ribbon.listOfServers=\
localhost:8080,localhost:8082
#配置日志级别
logging.level.xx.clients.OrderServiceFeignClient=DEBUG
# 日志输出配置
# @Configuration
# public class FeignLogConfig {
# @Bean
# Logger.Level feignLogger(){
# return Logger.Level.FULL;
# }
# }
源码跟踪
自动装配注解@EnableFeignClients
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] basePackages() default {};
}
客户端注册FeignClientsRegistrar
class FeignClientsRegistrar
implements ImportBeanDefinitionRegistrar{
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//注册默认的配置
registerDefaultConfiguration(metadata, registry);
//具体的注册客户
registerFeignClients(metadata, registry);
}
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
//向spring容器注册FeignClientFactoryBean
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
}
}
客户工厂类FeignClientFactoryBean
class FeignClientFactoryBean
implements FactoryBean<Object>{
<T> T getTarget() {
//获取上下文
FeignContext context = this.applicationContext.getBean(FeignContext.class);
//根据上下文创建复杂对象的构建者
Feign.Builder builder = feign(context);
//负载均衡包装
client = ((LoadBalancerFeignClient) client).getDelegate();
builder.client(client);
//动态代理客户端
return (T) targeter.target(this, builder, context,
new HardCodedTarget<>(this.type, this.name, url));
}
}
动态代理客户端ReflectiveFeign
//动态代理
public <T> T newInstance(Target<T> target) {
//服务节点封装器
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class<?>[] {target.type()}, handler);
}
//具体代理对象
static class FeignInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//使用策略模式调用具体的服务节点
return dispatch.get(method).invoke(args);
}
}
请求解析并调用
class SynchronousMethodHandler implements MethodHandler {
public Object invoke(Object[] argv){
//构建请求模板
RequestTemplate template = buildTemplateFromArgs.create(argv);
//发出请求并解码返回的数据
return executeAndDecode(template, options);
}
Object executeAndDecode(RequestTemplate template, Options options){
//LoadBalancerFeignClient进行调用,并负载均衡
response = client.execute(request, options);
}
}