例子此次先不写了。。。直接源码走起。部分设计跟Ribbon同样,这边就不在累述,建议先看Ribbon系列。
依然从spring.factories提及。注意到这里有这几个类:FeignAutoConfiguration、FeignRibbonClientAutoConfiguration。spring
加载FeignContext,这里会赋值FeignClientSpecification的集合,
后面说FeignClientSpecification类怎么来的,其实跟Ribbon用的是同一个方法。
FeignContext的defaultConfigType是FeignClientsConfiguration.class,这个和Ribboon用法同样,后面会加载。segmentfault
@Autowired(required = false) private List<FeignClientSpecification> configurations = new ArrayList<>(); @Bean public FeignContext feignContext() { FeignContext context = new FeignContext(); context.setConfigurations(this.configurations); return context; }
另外一个加载的是HystrixTargeter,虽然是HystrixTargeter,若是Feign.Builder不是feign.hystrix.HystrixFeign.Builder,后面调用的仍是Feign.Builder的target方法。app
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(name = "feign.hystrix.HystrixFeign") protected static class HystrixFeignTargeterConfiguration { @Bean @ConditionalOnMissingBean public Targeter feignTargeter() { return new HystrixTargeter(); } }
加载CachingSpringLoadBalancerFactory,这个类会注入SpringClientFactory,看过了Ribbon,是否是就知道了他要作什么。没错,他会建立一个ILoadBalancer,用于负载均衡。负载均衡
@Bean @Primary @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") public CachingSpringLoadBalancerFactory cachingLBClientFactory( SpringClientFactory factory) { return new CachingSpringLoadBalancerFactory(factory); }
FeignRibbonClientAutoConfiguration还import了DefaultFeignLoadBalancedConfiguration类,在这个类,会建立一个LoadBalancerFeignClient,后面须要的Client就是他了。ide
@Bean @ConditionalOnMissingBean public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory, clientFactory); }
咱们使用feign的时候,都会使用这个注解,注解里Import了FeignClientsRegistrar这个类,FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口,调用registerBeanDefinitions方法。这个方法作了两件事,一件事是注册FeignClientSpecification类,后面会注入到上面的FeignContext中,这个用法跟Ribbon - 几种自定义负载均衡策略提的同样。另一件事就是建立FactoryBean。ui
@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // 注册FeignClientSpecification类 registerDefaultConfiguration(metadata, registry); // 经过注解的信息注册FeignClientFactoryBean类, //这个是FactoryBean,因此容器fresh的时候会调用他的getObject方法 registerFeignClients(metadata, registry); }
这个方法就会扫描EnableFeignClients和FeignClient的注解,而后注册FeignClientFactoryBean类型的bean,这个是FactoryBean,因此容器fresh的时候会调用他的getObject方法。this
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<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients"); // 若是EnableFeignClients没有配置clients信息,扫描FeignClient注解 if (clients == null || clients.length == 0) { ClassPathScanningCandidateComponentProvider scanner = getScanner(); scanner.setResourceLoader(this.resourceLoader); // 扫描FeignClient注解 scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class)); Set<String> basePackages = getBasePackages(metadata); for (String basePackage : basePackages) { candidateComponents.addAll(scanner.findCandidateComponents(basePackage)); } } else { // 若是配置clients信息,就忽略FeignClient注解,直接读取clients信息 for (Class<?> clazz : clients) { candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz)); } } 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"); Map<String, Object> attributes = annotationMetadata .getAnnotationAttributes(FeignClient.class.getCanonicalName()); String name = getClientName(attributes); registerClientConfiguration(registry, name, attributes.get("configuration")); // 注册FeignClientFactoryBean registerFeignClient(registry, annotationMetadata, attributes); } } }
getObject会调用getTarget方法,他会建立一个Feign.Builder,建立的时候会传FeignContext,这个FeignContext的加载在上面已经提过了。而后调用loadBalance方法返回代理对象,这个代理就是后面远程调用用的。编码
<T> T getTarget() { FeignContext context = applicationContext.getBean(FeignContext.class); Feign.Builder builder = feign(context); if (!StringUtils.hasText(url)) { if (!name.startsWith("http")) { url = "http://" + name; } else { url = name; } url += cleanPath(); return (T) loadBalance(builder, context, new HardCodedTarget<>(type, name, url)); } // 直接ip的形式,代码略 }
建立一个Feign.Builder,FeignContext#getInstance,这个类继承了NamedContextFactory,流程和ribbon的SpringClientFactory#getContext同样。上面提到FeignContext的defaultConfigType是FeignClientsConfiguration.class,因此还会加载OptionalDecoder解码、SpringEncoder编码、SpringMvcContract,解析MVC注解、NEVER_RETRY重试、DefaultFeignLoggerFactory日志、FeignClientConfigurer、Feign.builder()。url
protected Feign.Builder feign(FeignContext context) { FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class); Logger logger = loggerFactory.create(type); // @formatter:off Feign.Builder builder = get(context, Feign.Builder.class) // required values .logger(logger) .encoder(get(context, Encoder.class)) .decoder(get(context, Decoder.class)) .contract(get(context, Contract.class)); // @formatter:on // 整合配置Feign.Builder configureFeign(context, builder); return builder; }
这里获取Client和Targeter类,Client就是上面的LoadBalancerFeignClient,他是全部共享的。Targeter是HystrixTargeter,他是serviceId私有的。上面已经提了他最终是调用Feign.Builder#target。spa
protected <T> T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget<T> target) { Client client = getOptional(context, Client.class); if (client != null) { builder.client(client); Targeter targeter = get(context, Targeter.class); return targeter.target(this, builder, context, target); } // 异常略 }
build方法是构建一个ReflectiveFeign对象,newInstance是生成代理对象。
public <T> T target(Target<T> target) { return build().newInstance(target); }
build方法中,ReflectiveFeign建立的时候传了ParseHandlersByName,InvocationHandlerFactory,SynchronousMethodHandler三个对象。
public Feign build() { // 其余略 return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder); }
代理对象生成,生成后,后面对代理对象的访问,都会调用FeignInvocationHandler#invoke方法。
public <T> T newInstance(Target<T> target) { // ParseHandlersByName是经过Contrac用来解析接口定义。 Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); // 给每一个方法建立一个SynchronousMethodHandler对象 Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>(); List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>(); for (Method method : target.type().getMethods()) { if (method.getDeclaringClass() == Object.class) { continue; } else 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对象,这里是FeignInvocationHandler InvocationHandler handler = factory.create(target, methodToHandler); T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[] {target.type()}, handler); for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) { defaultMethodHandler.bindTo(proxy); } return proxy; }
启动的时候,为每一个接口,生成代理对象。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 其余略 //dispatch.get(method)获取的是SynchronousMethodHandler return dispatch.get(method).invoke(args); }
调用LoadBalancerFeignClient#execute,LoadBalancerFeignClient加载上面已经讲过了。
public Object invoke(Object[] argv) throws Throwable { RequestTemplate template = buildTemplateFromArgs.create(argv); // 其余略 return executeAndDecode(template, options); // 其余略 } Object executeAndDecode(RequestTemplate template, Options options) throws Throwable { // 其余略 response = client.execute(request, options); // 其余略 }
@Override public Response execute(Request request, Request.Options options) throws IOException { try { // 获取Uri URI asUri = URI.create(request.url()); // 获取serviceId String clientName = asUri.getHost(); URI uriWithoutHost = cleanUrl(request.url(), clientName); FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest( this.delegate, request, uriWithoutHost); IClientConfig requestConfig = getClientConfig(options, clientName); // 获取FeignLoadBalancer,经过FeignLoadBalancer调用请求 return lbClient(clientName) .executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse(); } catch (ClientException e) { IOException io = findIOException(e); if (io != null) { throw io; } throw new RuntimeException(e); } }
lbClientFactory是CachingSpringLoadBalancerFactory,因此调用CachingSpringLoadBalancerFactory#create的create方法。
CachingSpringLoadBalancerFactory有个熟悉的SpringClientFactory对象,他负责获取ILoadBalancer、IClientConfig、ServerIntrospector,而后经过这三个构建一个FeignLoadBalancer对象。既然获得了ILoadBalancer,那后续负载均衡的部分就再也不继续了,参考Ribbon - 负载均衡流程。
private FeignLoadBalancer lbClient(String clientName) { return this.lbClientFactory.create(clientName); } public FeignLoadBalancer create(String clientName) { FeignLoadBalancer client = this.cache.get(clientName); if (client != null) { return client; } IClientConfig config = this.factory.getClientConfig(clientName); ILoadBalancer lb = this.factory.getLoadBalancer(clientName); ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class); client = this.loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector, this.loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector); this.cache.put(clientName, client); return client; }
主要是经过代理对象,而后调用Ribbon进行负载均衡。咱们这边只讲述了主流程,怎么构建HTTP请求,怎么处理返回结果,都略过了。。。。。