Feign的用法
1.引入依賴 openfeign
<dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-openfeign</artifactId>
? ? ? ? </dependency>
2.在啟動類上加 @EnableFeignClients("Feign接口所在的包名")躏率。
3.編寫Feign接口尿招,在接口上加@FeignClient("被調(diào)用的服務名")障本。
4.在Feign接口中編寫方法(對應提供者的方法)匙握,方法可以使用SpringMVC的注解嘉冒。
5.注入接口對象,通過方法實現(xiàn)遠程調(diào)用伙单。
————————————————
如果有多個包脓恕,第二步需要配置多個包名
@EnableFeignClient的底層邏輯是:
@Import?FeignClientsRegistrar
這個Class 的定義:
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware,EnvironmentAware {
核心是解析@FeignClient注解的class,注冊到spring工廠中
public void registerFeignClients(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
SetbasePackages;
Mapattrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName());
AnnotationTypeFilter annotationTypeFilter =new AnnotationTypeFilter(
FeignClient.class);
final Class[]clients =attrs ==null ?null
? ? ? ? : (Class[])attrs.get("clients");
if (clients ==null ||clients.length ==0) {
scanner.addIncludeFilter(annotationTypeFilter);
basePackages = getBasePackages(metadata);
}
else {
final SetclientClasses =new HashSet<>();
basePackages =new HashSet<>();
for (Classclazz :clients) {
basePackages.add(ClassUtils.getPackageName(clazz));
clientClasses.add(clazz.getCanonicalName());
}
AbstractClassTestingTypeFilter filter =new AbstractClassTestingTypeFilter() {
@Override
? ? ? ? protected boolean match(ClassMetadata metadata) {
String cleaned = metadata.getClassName().replaceAll("\\$",".");
return clientClasses.contains(cleaned);
}
};
scanner.addIncludeFilter(
new AllTypeFilter(Arrays.asList(filter,annotationTypeFilter)));
}
for (String basePackage :basePackages) {
SetcandidateComponents =scanner
? ? ? ? ? ? .findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent :candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
? ? ? ? ? ? AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata =beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
Mapattributes =annotationMetadata
? ? ? ? ? ? ? ? ? .getAnnotationAttributes(
FeignClient.class.getCanonicalName());
String name = getClientName(attributes);
registerClientConfiguration(registry,name,
attributes.get("configuration"));
registerFeignClient(registry,annotationMetadata,attributes);
}
}
}
}
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata,Map attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition =BeanDefinitionBuilder
? ? ? ? .genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name",name);
definition.addPropertyValue("type",className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias =name +"FeignClient";
AbstractBeanDefinition beanDefinition =definition.getBeanDefinition();
boolean primary = (Boolean)attributes.get("primary");// has a default, won't be null
? beanDefinition.setPrimary(primary);
String qualifier = getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias =qualifier;
}
BeanDefinitionHolder holder =new BeanDefinitionHolder(beanDefinition,className,
new String[] { alias });
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder,BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
? String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
? String[]aliases = definitionHolder.getAliases();
if (aliases !=null) {
for (String alias :aliases) {
registry.registerAlias(beanName,alias);
}
}
}