Feign的用法
1.引入依赖 openfeign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在启动类上加 @EnableFeignClients("Feign接口所在的包名")。
3.编写Feign接口,在接口上加@FeignClient("被调用的服务名")。
4.在Feign接口中编写方法(对应提供者的方法),方法可以使用SpringMVC的注解。
5.注入接口对象,通过方法实现远程调用。
————————————————
如果有多个包,第二步需要配置多个包名
@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);
}
}
}
网友评论