在了解服务注册
与反注册
后,就该到服务调用环节了。
进行服务调用之前,需要组装请求头、请求体,构建客户端对象,通过服务提供方url地址调用远程服务。此方式虽然可以实现远程调用,但是需要使用者了解底层调用,并且还会给开发人员带来重复编码的问题。
为此,今天就来了解下SpringCloud
的OpenFeign
是如何实现远程调用的
3.服务调用
3.1 开启Feign远程调用
当我们需要使用feign
进行远程调用时,只需要在入口处加上@EnableFeignClients
注解即可
3.2 扫描FeignClient注解标注的接口
@EnableFeignClients
注解引入FeignClientsRegistrar
配置类,该配置类会执行扫描动作,扫描项目中被@FeignClient
注解标注的接口
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set<String> basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
复制代码
关键代码:
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
3.3 创建并注册FeignClientFactoryBean
遍历3.2
中扫描到的组件,每个组件创建一个FeignClientFactoryBean
并注入到IOC
容器中,FeignClientFactoryBean
的类型就是使用@FeignClient
标注的接口
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata,
Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
Class clazz = ClassUtils.resolveClassName(className, null);
ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory
? (ConfigurableBeanFactory) registry : null;
String contextId = getContextId(beanFactory, attributes);
String name = getName(attributes);
// 1. 创建FeignClientFactoryBean
FeignClientFactoryBean factoryBean = new FeignClientFactoryBean();
// 2. 设置属性
factoryBean.setBeanFactory(beanFactory);
factoryBean.setName(name);
factoryBean.setContextId(contextId);
factoryBean.setType(clazz);
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
factoryBean.setUrl(getUrl(beanFactory, attributes));
factoryBean.setPath(getPath(beanFactory, attributes));
factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));
Object fallback = attributes.get("fallback");
if (fallback != null) {
factoryBean.setFallback(fallback instanceof Class ? (Class<?>) fallback
: ClassUtils.resolveClassName(fallback.toString(), null));
}
Object fallbackFactory = attributes.get("fallbackFactory");
if (fallbackFactory != null) {
factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class<?>) fallbackFactory
: ClassUtils.resolveClassName(fallbackFactory.toString(),