
源码仓库Gitee·GitHub一. EnableFeignClients1.1.类介绍从上面注释可以看出是扫描声明了FeignClient接口的类还引入了 FeignClientsRegistrar类从字面意思可以看出是进行了 FeignClient 客户端类的注册。1.2.FeignClientsRegistrar 详解最主要的一个方法registerBeanDefinitions注册bean定义信息主要功能是实现向容器注册Feign客户端配置信息和所有的使用了FeignClient的类1.2.1.registerDefaultConfiguration()private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // 获取EnableFeignClients注解的属性和值 MapString, Object defaultAttrs metadata .getAnnotationAttributes(EnableFeignClients.class.getName(), true); // 获取属性中的默认配置 defaultConfigurationname是main主程序 if (defaultAttrs ! null defaultAttrs.containsKey(defaultConfiguration)) { String name; if (metadata.hasEnclosingClass()) { name default. metadata.getEnclosingClassName(); } else { name default. metadata.getClassName(); } //默认配置信息进行容器注册 registerClientConfiguration(registry, name, defaultAttrs.get(defaultConfiguration)); } }1.2.1.1.registerClientConfigurationprivate void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { // 创建一个 FeignClientSpecification.class 构造器 BeanDefinitionBuilder builder BeanDefinitionBuilder .genericBeanDefinition(FeignClientSpecification.class); builder.addConstructorArgValue(name); builder.addConstructorArgValue(configuration); // 向容器中注册默认配置 registry.registerBeanDefinition( name . FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition()); }1.2.1.2.registerBeanDefinition核心代码在org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinitionpublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { ............ if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { //放到beanDefinitionMap到AbstractApplicationContext#finishBeanFactoryInitialization(beanFactory)中取出进行bean实例化 //此时是处于invokeBeanFactoryPostProcessors(beanFactory);阶段进行BeanDefinitionRegistryPostProcessor的处理 this.beanDefinitionMap.put(beanName, beanDefinition); ListString updatedDefinitions new ArrayList(this.beanDefinitionNames.size() 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames updatedDefinitions; removeManualSingletonName(beanName); } } .......... }1.2.2.registerFeignClients()public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //获取一个扫描器 ClassPathScanningCandidateComponentProvider scanner getScanner(); //设置资源路径 scanner.setResourceLoader(this.resourceLoader); //包路径 SetString basePackages; //获取EnableFeignClients注解的参数和值有5个值其中clients对应的class[0]是没有值的 MapString, Object attrs metadata .getAnnotationAttributes(EnableFeignClients.class.getName()); //定义一个 FeignClient 注解类型过滤器 AnnotationTypeFilter annotationTypeFilter new AnnotationTypeFilter( FeignClient.class); //clients为class[0]长度为0 final Class?[] clients attrs null ? null : (Class?[]) attrs.get(clients); if (clients null || clients.length 0) { //FeignClient 注解过滤器添加到扫描器中 scanner.addIncludeFilter(annotationTypeFilter); //获取Application对应的根路径包 basePackages getBasePackages(metadata); } //clients不为空FeignClient 注解过滤器添加到扫描器中、获取包路径 else { final SetString clientClasses new HashSet(); basePackages new HashSet(); for (Class? clazz : 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))); } //遍历包路径获取标记FeignClient注解的接口向容器中注入 for (String basePackage : basePackages) { SetBeanDefinition candidateComponents 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); //获取FeignClient的参数和值 MapString, Object attributes annotationMetadata .getAnnotationAttributes( FeignClient.class.getCanonicalName()); String name getClientName(attributes); //再次更新配置 registerClientConfiguration(registry, name, attributes.get(configuration)); //注册 registerFeignClient(registry, annotationMetadata, attributes); } } } }1.2.2.2.registerFeignClient//定义一个 FeignClientFactoryBean bean定义构造器(重点 BeanDefinitionBuilder definition BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class); .......... //前面根据attributes进行属性赋值后注入到Spring容器中 BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);二.FeignClient从上面可以看到在注册客户端时注册了一个FeignClientFactoryBean对于FactoryBean的扩展知识和案例所以FeignClient的获取是从getObject()获取的2.1.getTarget()T T getTarget() { //获取创建feign实例的工厂 FeignContext context this.applicationContext.getBean(FeignContext.class); //获取feign构造器 Feign.Builder builder feign(context); //url拼接 if (!StringUtils.hasText(this.url)) { //拼接name if (!this.name.startsWith(http)) { this.url http:// this.name; } else { this.url this.name; } //拼接path this.url cleanPath(); //创建实例 return (T) loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url)); } if (StringUtils.hasText(this.url) !this.url.startsWith(http)) { this.url http:// this.url; } String url this.url cleanPath(); Client client getOptional(context, Client.class); if (client ! null) { if (client instanceof LoadBalancerFeignClient) { // not load balancing because we have a url, // but ribbon is on the classpath, so unwrap client ((LoadBalancerFeignClient) client).getDelegate(); } builder.client(client); } Targeter targeter get(context, Targeter.class); return (T) targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url)); }2.1.1. feign()//添加日志对象、编码器、解码器、解析规则器 protected Feign.Builder feign(FeignContext context) { FeignLoggerFactory loggerFactory get(context, FeignLoggerFactory.class); Logger logger loggerFactory.create(this.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)) //SpringMvcContract:对RequestMapping、RequestParam、RequestHeader等注解进行解析 .contract(get(context, Contract.class)); // formatter:on configureFeign(context, builder); return builder; }2.1.2. loadBalance()protected T T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTargetT target) { //根据context上下文获取客户端实例client:TraceLoadBalancerFeignClient,负载均衡 Client client getOptional(context, Client.class); if (client ! null) { //客户端创建 builder.client(client); //获取HystrixTargerer Targeter targeter get(context, Targeter.class); //调用HystrixTargeter#target进行实例创建 return targeter.target(this, builder, context, target); } throw new IllegalStateException( No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?); }2.1.3. HystrixTargeter#targetclass HystrixTargeter implements Targeter { Override public T T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, Target.HardCodedTargetT target) { // 不是同一种类型进入feign#target方法 if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) { return feign.target(target); } ...... }2.1.4. Feign.Builder#targetpublic T T target(TargetT target) { return build().newInstance(target); }2.1.4.1. Feign.Builder#targetpublic Feign build() { //同步方法处理工厂构建了日志级别信息 SynchronousMethodHandler.Factory synchronousMethodHandlerFactory new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger, logLevel, decode404, closeAfterDecode, propagationPolicy); //解析信息编码、解密、同步方法处理工厂 ParseHandlersByName handlersByName new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder, errorDecoder, synchronousMethodHandlerFactory); //new对象 return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder); }2.1.4.2.ReflectiveFeign#newInstanceOverride public T T newInstance(TargetT target) { //得到feign类的定义方法 MapString, MethodHandler nameToHandler targetToHandlersByName.apply(target); //定义方法存放集合 MapMethod, MethodHandler methodToHandler new LinkedHashMapMethod, MethodHandler(); //默认方法存放集合 ListDefaultMethodHandler defaultMethodHandlers new LinkedListDefaultMethodHandler(); //对feign类方法进行遍历 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))); } } //jdk动态代理创建对象 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; }三.总结主要应用了FactoryBean的特性getObject()进行jdk动态创建一个ReflectiveFeign的代理对象。