Open Feign架构 - 远程通信的利器

前言

Feign 是一个声明式的 web service 客户端。Spring Cloud 中的 Open Feign 在 Feign 的基础上支持 Spring MVC 注解、JAX-RS 注解,同时集成了 Ribbon、Eureka(对于负载均衡,同样支持 Spring Cloud LoadBalancer)

对 @EnableFeignClients 注解进行解析,扫描指定路径下的所有标注 @FeignClient 注解的接口,解析其标注的 @FeignClient 注解,然后生成动态代理。最后组装成一个 Request 对象,进行远程通信。

代码样例

方式一 、服务提供者模块定义 Feign Client 接口

order-api模块

@RequestMapping("order")
public interface OrderService {
   
   

    @GetMapping("orders")
    String orders();
}
@FeignClient("spring-cloud-order")
public interface OrderServiceFeignClient extends OrderService {
   
   
}

order-application模块

@RestController
public class OrderServiceImpl implements OrderService {
   
   

    @Value("${server.port}")
    private Integer port;

    @Override
    public String orders() {
   
   
        return String.valueOf(port);
    }
}
server:
    port: 8081
spring:
    application:
        name: spring-cloud-order
server:
    port: 8082
spring:
    application:
        name: spring-cloud-order

user-service模块

@RestController
public class UserController {
   
   

    @Autowired
    private OrderServiceFeignClient orderServiceFeignClient;

    @GetMapping("user2")
    public String user2() {
   
   
        return orderServiceFeignClient.orders();
    }
}
@SpringBootApplication
@EnableFeignClients(basePackages = {
   
   
        "com.mzs.order.api.clients"
})
public class SpringCloudUserApplication {
   
   

    public static void main(String[] args) {
   
   
        SpringApplication.run(SpringCloudUserApplication.class, args);
    }

}

方式二 、在服务消费者模块定义 Feign Client 接口

order-api模块

public interface OrderService {
   
   

    String orders();
}

order-service模块

@RestController
@RequestMapping("order")
public class OrderController {
   
   

    @Autowired
    private OrderService orderService;

    @GetMapping("orders")
    public String orders() {
   
   
        return orderService.orders();
    }
}
server:
    port: 8081
spring:
    application:
        name: spring-cloud-order
server:
    port: 8082
spring:
    application:
        name: spring-cloud-order

user-service模块

@FeignClient("spring-cloud-order")
@RequestMapping("order")
public interface OrderServiceFeignClient {
   
   

    @GetMapping("orders")
    String orders();
}
spring-cloud-order:
    ribbon:
        listOfServers: localhost:8081,localhost:8082
@RestController
public class UserController {
   
   

    @Autowired
    private OrderServiceFeignClient orderServiceFeignClient;

    @GetMapping("user2")
    public String user2() {
   
   
        return orderServiceFeignClient.orders();
    }
}
@SpringBootApplication
@EnableFeignClients
public class SpringCloudUserApplication {
   
   

    public static void main(String[] args) {
   
   
        SpringApplication.run(SpringCloudUserApplication.class, args);
    }

}

源码分析

一、@EnableFeignClients

用于扫描所有标注 @FeignClient注解的接口。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
   
   
 	...... 
}

二、FeignClientsRegistrar

FeignClientsRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,看下 registerBeanDefitions(…) 方法的具体实现,如下:

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   
   
   // 注册 @EnableFeignClients 注解 defaultConfiguration 属性指定的配置类
   registerDefaultConfiguration(metadata, registry);
   // 获取 @FeignClient 注解的属性以及属性值,填充到 FeignClientFactoryBean 
   // 从而注册到 IOC 容器中
   registerFeignClients(metadata, registry);
}

1、registerDefaultConfiguration(…) 方法

private void registerDefaultConfiguration(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   
   
   // 获取 @EnableFeignClients 注解的属性以及属性值
   Map<String, Object> defaultAttrs = metadata
         .getAnnotationAttributes(EnableFeignClients.class.getName(), true);
   // 如果 @EnableFeignClients 注解有指定 defaultConfiguration 属性
   if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
   
   
      String name;
      if (metadata.hasEnclosingClass()) {
   
   
         name = "default." + metadata.getEnclosingClassName();
      }
      else {
   
   
         name = "default." + metadata.getClassName();
      }
      // 注册指定的配置类
      registerClientConfiguration(registry, name,
            defaultAttrs.get("defaultConfiguration"));
   }
}
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
      Object configuration) {
   
   
   // 创建关于FeignClientSpecification的BeanDefinitionBuilder实例
   BeanDefinitionBuilder builder = BeanDefinitionBuilder
         .genericBeanDefinition(FeignClientSpecification.class);
   builder.addConstructorArgValue(name);
   // 将@EnableFeignClients 注解 defaultConfiguration 属性指定的配置类封装到 FeignClientSpecification
   builder.addConstructorArgValue(configuration);
   // 注册到 IOC 容器中
   registry.registerBeanDefinition(
         name + "." + FeignClientSpecification.class.getSimpleName(),
         builder.getBeanDefinition());
}

2、registerFeignClients(…) 方法

public void registerFeignClients(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   
   

   LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();
   // 获取 @EnableFeignClients 注解的属性以及属性值
   Map<String, Object> attrs = metadata
         .getAnnotationAttributes(EnableFeignClients.class.getName());
   AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
         FeignClient.class);
   final Class<?>[
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值