
文章目录
1. @EnableFeignClients注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients
我们使用@EnableFeignClients来开启feign的功能。从源码中看,该注解主要作用是通过@Import注解引入FeignClientsRegistrar类,追踪源码。
2. 注入类FeignClientsRegistrar.class
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware
该类实现了ResourceLoaderAware,BeanClassLoaderAware,EnvironmentAware接口,在解析@import注解的过程中会将感兴趣的bean注入到该类中。实现了ImportBeanDefinitionRegisterar接口,通过重写registerBeanDefinitions方法来注册默认的feign配置类和注册feignClients对应的FeignClientFactoryBean到容器当中。看一下源码:
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry); // 注册@EnableFeignClients指定的默认配置类到容器
this.registerFeignClients(metadata, registry);//注册feignClients对应的feignClientFactoryBean到容器
}
注册feignclients,实际上是其对应的工厂bean
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);// 注解扫描器
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class); // 设置扫描的目标注解
Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
Object basePackages;
if (clients != null && clients.length != 0) {
.........
Iterator var17 = ((Set)basePackages).iterator();
while(var17.hasNext()) {
String basePackage = (String)var17.next();
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
Iterator var21 = candidateComponents.iterator();
while(var21.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var21.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = this.getClientName(attributes);
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
注册方法:registerFeignClient
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes)
3 FeignClientFactoryBean类
FeignClientFactoryBean 是一个工厂bean,提供了获取FeignClient代理bean的getObject方法,直接看一下方法源码:
public Object getObject() throws Exception
4 生成feign代理类的,追踪源码到ReflectiveFeign。
public Object getObject() throws Exception {
FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class);
Builder builder = this.feign(context);
........
Targeter targeter = (Targeter)this.get(context, Targeter.class);
return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
}
}
public <T> T target(Target<T> target) {
return this.build().newInstance(target);
}
public <T> T newInstance(Target<T> target) {
Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
Method[] var5 = target.type().getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method method = var5[var7];
if (method.getDeclaringClass() != Object.class) {
if (Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
}
InvocationHandler handler = this.factory.create(target, methodToHandler);
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
while(var12.hasNext()) {
DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
本文详细探讨了SpringCloud中FeignClient的工作原理,从@EnableFeignClients注解开始,解释了其如何引入FeignClientsRegistrar类,接着分析了FeignClientsRegistrar如何注册Feign配置和客户端。然后,重点介绍了FeignClientFactoryBean的角色,特别是getObject方法在生成Feign代理类中的作用。最后,文章追踪源码至ReflectiveFeign,揭示了Feign代理类的创建过程。

1603

被折叠的 条评论
为什么被折叠?



