Feign代理类的生成过程

 
 
EnableFeignClients 这个注解开启了FeignClient的解析过程
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] defaultConfiguration() default {};

    Class<?>[] clients() default {};
}
它通过@Import注解来导入一个配置类FeignClientsRegistrar,FeignClientsRegistrar实现了ImportBeanDefifinitionRegistrar,它拥有动态注入bean的能力,Spring Boot启动的时候,会去调用这个类中的registerBeanDefifinitions来实现动态Bean的装载。
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    /**注册@EnableFeignClients中定义defaultConfiguration属性下的类,包装成 FeignClientSpecification,
      注册到Spring容器。在@FeignClient中有一个属性:configuration,这个属性是表示各个FeignClient
      自定义的配置类,后面也会通过调用registerClientConfiguration方法来注册成FeignClientSpecification 
      到容器。所以,这里可以完全理解在@EnableFeignClients中配置的是做为兜底的配置,在各个@FeignClient 
      配置的就是自定义的情况。**/
    this.registerDefaultConfiguration(metadata, registry);
    /**将带有FeignClient的注解的接口注册到Spring容器中**/
    this.registerFeignClients(metadata, registry);
}
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
    scanner.setResourceLoader(this.resourceLoader);
    Map attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
    //过滤出所有的带有FeignClient注解的类
    AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
    Class[] clients = attrs == null?null:(Class[])((Class[])attrs.get("clients"));
    Object basePackages;
    if(clients != null && clients.length != 0) {
        final HashSet clientClasses = new HashSet();
        basePackages = new HashSet();
        Class[] basePackage = clients;
        int candidateComponents = clients.length;

        for(int var11 = 0; var11 < candidateComponents; ++var11) {
            Class candidateComponent = basePackage[var11];
            ((Set)basePackages).add(ClassUtils.getPackageName(candidateComponent));
            clientClasses.add(candidateComponent.getCanonicalName());
        }

        AbstractClassTestingTypeFilter var18 = new AbstractClassTestingTypeFilter() {
            protected boolean match(ClassMetadata metadata) {
                String cleaned = metadata.getClassName().replaceAll("\\$", ".");
                return clientClasses.contains(cleaned);
            }
        };
        scanner.addIncludeFilter(new FeignClientsRegistrar.AllTypeFilter(Arrays.asList(new TypeFilter[]{var18, annotationTypeFilter})));
    } else {
        scanner.addIncludeFilter(annotationTypeFilter);
        //获取EnableFeignClients设置的包扫描路径
        basePackages = this.getBasePackages(metadata);
    }

    Iterator var17 = ((Set)basePackages).iterator();

    while(var17.hasNext()) {
        String var19 = (String)var17.next();
        //扫描包路径下的所有类,并筛选出所有带有FeignClient注解的类,转化为BeanDefinition集合
        Set var20 = scanner.findCandidateComponents(var19);
        Iterator var21 = var20.iterator();
        while(var21.hasNext()) {
            BeanDefinition var22 = (BeanDefinition)var21.next();
            if(var22 instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)var22;
                AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
                Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
                //获取FeignClient注解信息
                Map attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
                String name = this.getClientName(attributes);
                //以FeignClient注解配置的服务名称为BeanDefinition的名称前缀,注册FeignClientSpecification
                this.registerClientConfiguration(registry, name, attributes.get("configuration"));
                //将带有FeignClient注解的类设置代理,注册到Spring容器
                this.registerFeignClient(registry, annotationMetadata, attributes);
            }
        }
    }

}
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
    String className = annotationMetadata.getClassName();
    //FeignClientFactoryBean是一个FactoryBean,Spring容器实例化对象时会调用它的getObject方法。
    BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
    this.validate(attributes);
    definition.addPropertyValue("url", this.getUrl(attributes));
    definition.addPropertyValue("path", this.getPath(attributes));
    String name = this.getName(attributes);
    definition.addPropertyValue("name", name);
    String contextId = this.getContextId(attributes);
    definition.addPropertyValue("contextId", contextId);
    //definition的type设置为标注有FeignClient注解的实际接口名称
    definition.addPropertyValue("type", className);
    definition.addPropertyValue("decode404", attributes.get("decode404"));
    definition.addPropertyValue("fallback", attributes.get("fallback"));
    definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
    definition.setAutowireMode(2);
    String alias = contextId + "FeignClient";
    AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
    beanDefinition.setAttribute("factoryBeanObjectType", className);
    boolean primary = ((Boolean)attributes.get("primary")).booleanValue();
    beanDefinition.setPrimary(primary);
    String qualifier = this.getQualifier(attributes);
    if(StringUtils.hasText(qualifier)) {
        alias = qualifier;
    }
    //BeanDefinitionHolder 的beanName设置为标注有FeignClient注解的实际接口名称
    BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
    BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}

着重查看registerFeignClients方法,FeignClientsRegistrar.registerFeignClients 方法会扫描basePackages路径下所有的@FeignClient注解,再用扫描出来的类循环调用registerFeignClient方法,在FeignClientsRegistrar.registerFeignClient方法中,设置BeanDefinition的BeanClass为FeignClientFactoryBean,并将FeignClient注解的信息设置到BeanDefinition中,然后将这个BeanDefinition注册到Spring容器中。我们知道FeignClientFactoryBean是一个FactoryBean,Spring实例化BeanDefinition的时候会调用它的getObject方法。

public Object getObject() throws Exception {
    return this.getTarget();
}

<T> T getTarget() {
    //FeignContext是在FeignAutoConfiguration中初始化的    
    FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class);
    //构建Builder对象
    Builder builder = this.feign(context);
    //如果FeignClient注解上没设置Url,走负载均衡,生成具有负载均衡功能的代理类
    if(!StringUtils.hasText(this.url)) {
        if(!this.name.startsWith("http")) {
            this.url = "http://" + this.name;
        } else {
            this.url = this.name;
        }
        this.url = this.url + this.cleanPath();
        return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url));
    } else {
        if(StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
            this.url = "http://" + this.url;
        }
        String url = this.url + this.cleanPath();
        Client client = (Client)this.getOptional(context, Client.class);
        if(client != null) {
            if(client instanceof LoadBalancerFeignClient) {
                client = ((LoadBalancerFeignClient)client).getDelegate();
            }
            if(client instanceof FeignBlockingLoadBalancerClient) {
                client = ((FeignBlockingLoadBalancerClient)client).getDelegate();
            }
            builder.client(client);
        }
        Targeter targeter = (Targeter)this.get(context, Targeter.class);
        return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
    }
}
protected Builder feign(FeignContext context) {
    FeignLoggerFactory loggerFactory = (FeignLoggerFactory)this.get(context, FeignLoggerFactory.class);
    Logger logger = loggerFactory.create(this.type);
    //获取服务名称对应的Spring容器,并从容器中获取Builder、Encoder、Decoder、Contract等实例化对象
    Builder builder = ((Builder)this.get(context, Builder.class)).logger(logger).encoder((Encoder)this.get(context, Encoder.class)).decoder((Decoder)this.get(context, Decoder.class)).contract((Contract)this.get(context, Contract.class));
    this.configureFeign(context, builder);
    return builder;
}
protected <T> T get(FeignContext context, Class<T> type) {
    /**调用父类NamedContextFactory的getInstance,和Ribbon的SpringClientFactory的设计一样,通过
    contextId(服务名称)来做容器的隔离,FeignContext向每个Spring容器注册了FeignClientsConfiguration配置类,
    初始化了Decoder、Encoder、Contract等;但是每个容器初始化的FeignClientsConfiguration配置都是一样,没有
    体现服务隔离的必要性,这里不是很理解**/
    Object instance = context.getInstance(this.contextId, type);
    if(instance == null) {
        throw new IllegalStateException("No bean found of type " + type + " for " + this.contextId);
    } else {
        return instance;
    }
}
public <T> T getInstance(String name, Class<T> type) {
    AnnotationConfigApplicationContext context = this.getContext(name);
    return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0?context.getBean(type):null;
}

在FeignClientFactoryBean.getObject方法中,调用了FeignClientFactoryBean.getTarget方法,首先通过applicationContext获取FeignContext实例,然后调用FeignClientFactoryBean.feign方法,通过contextId(服务名称)从FeignContext中获取服务名称对应的Spring容器(如果没有对应服务名称的服务器,那么创建一个新的Spring容器,将原本的Spring容器作为这个新容器的父容器,向新容器中注册FeignClientsConfiguration类),并从Spring容器获取对应的Builder及Builder需要的各种成员变量。

protected <T> T loadBalance(Builder builder, FeignContext context, HardCodedTarget<T> target) {
    Client client = (Client)this.getOptional(context, Client.class);
    if(client != null) {
        builder.client(client);
        Targeter targeter = (Targeter)this.get(context, Targeter.class);
        return targeter.target(this, builder, context, target);
    } else {
        throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
    }
}

 构建好Builder后,如果url为空,调用FeignClientFactoryBean.loadBalance方法,生成具有负载均衡功能的代理类。其中targeter实例是在FeignAutoConfiguration中生成的,targeter.target()方法最终会调用Feign.target方法,在Feign的实现类ReflectiveFeign的newInstance方法中生成代理类,在ReflectiveFeign.newInstance方法中首先调用ParseHandlersByName.apply方法将FeignClient的所有方法都封装成MethodHandler(SynchronousMethodHandler,并以类名加方法名称为Key保存在Map结构中,类似于Spring的HandlerMethod设计,最后生成FeignInvocationHandler代理返回。

public <T> T target(Target<T> target) {
    return this.build().newInstance(target);
}
public <T> T newInstance(Target<T> target) {
    //将所有FeignClient的接口解析封装成SynchronousMethodHandler
    Map nameToHandler = this.targetToHandlersByName.apply(target);
    LinkedHashMap methodToHandler = new LinkedHashMap();
    LinkedList defaultMethodHandlers = new LinkedList();
    Method[] handler = target.type().getMethods();
    int proxy = handler.length;
    for(int var7 = 0; var7 < proxy; ++var7) {
        Method defaultMethodHandler = handler[var7];
        if(defaultMethodHandler.getDeclaringClass() != Object.class) {
            if(Util.isDefault(defaultMethodHandler)) {
                DefaultMethodHandler handler1 = new DefaultMethodHandler(defaultMethodHandler);
                defaultMethodHandlers.add(handler1);
                methodToHandler.put(defaultMethodHandler, handler1);
            } else {
                methodToHandler.put(defaultMethodHandler, nameToHandler.get(Feign.configKey(target.type(), defaultMethodHandler)));
            }
        }
    }
    InvocationHandler var10 = this.factory.create(target, methodToHandler);
    Object var11 = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, var10);
    Iterator var12 = defaultMethodHandlers.iterator();
    while(var12.hasNext()) {
        DefaultMethodHandler var13 = (DefaultMethodHandler)var12.next();
        var13.bindTo(var11);
    }
    return var11;
}

 ParseHandlersByName.apply

public Map<String, MethodHandler> apply(Target target) {
    //将FeignClient中的所有方法信息都封装到MethodMetadata中
    List metadata = this.contract.parseAndValidateMetadata(target.type());
    LinkedHashMap result = new LinkedHashMap();
    Iterator var4 = metadata.iterator();
    while(var4.hasNext()) {
        MethodMetadata md = (MethodMetadata)var4.next();
        Object buildTemplate;
        if(!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
            buildTemplate = new ReflectiveFeign.BuildFormEncodedTemplateFromArgs(md, this.encoder, this.queryMapEncoder, target);
        } else if(md.bodyIndex() != null) {//一般是post请求,但是参数没有注解是默认会放到body里面
            buildTemplate = new ReflectiveFeign.BuildEncodedTemplateFromArgs(md, this.encoder, this.queryMapEncoder, target);
        } else {//正常的get请求
            buildTemplate = new ReflectiveFeign.BuildTemplateByResolvingArgs(md, this.queryMapEncoder, target);
        }
        if(md.isIgnored()) {
            result.put(md.configKey(), (args) -> {
                throw new IllegalStateException(md.configKey() + " is not a method handled by feign");
            });
        } else {
            //以类名#方法名(参数类型)组成的字符串为key(具体查看Feign.configKey方法),将MethodMetadata封装到     
              SynchronousMethodHandler中。
            result.put(md.configKey(), this.factory.create(target, md, (Factory)buildTemplate, this.options, this.decoder, this.errorDecoder));
        }
    }
    return result;
}

BaseContract.parseAndValidateMetadata

public List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
    LinkedHashMap result = new LinkedHashMap();
    //获取接口所有的方法
    Method[] var3 = targetType.getMethods();
    int var4 = var3.length;
    for(int var5 = 0; var5 < var4; ++var5) {
        Method method = var3[var5];
        if(method.getDeclaringClass() != Object.class && (method.getModifiers() & 8) == 0 && !Util.isDefault(method)) {
          //对每个方法进行解析(包括注解信息),并保存到MethodMetadata中,如果存在接口方法上没有RequestMapping,会报错提示
            MethodMetadata metadata = this.parseAndValidateMetadata(targetType, method);
            result.put(metadata.configKey(), metadata);
        }
    }
    return new ArrayList(result.values());
}

SpringMvcContract.parseAndValidateMetadata

public MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
    this.processedMethods.put(Feign.configKey(targetType, method), method);
    //将method的信息解析出来封装到MethodMetadata 中
    MethodMetadata md = super.parseAndValidateMetadata(targetType, method);
    RequestMapping classAnnotation = (RequestMapping)AnnotatedElementUtils.findMergedAnnotation(targetType, RequestMapping.class);
    if(classAnnotation != null) {
        //封装RequestMapping 配置的请求头信息
        if(!md.template().headers().containsKey("Accept")) {
            this.parseProduces(md, method, classAnnotation);
        }
        if(!md.template().headers().containsKey("Content-Type")) {
            this.parseConsumes(md, method, classAnnotation);
        }
        this.parseHeaders(md, method, classAnnotation);
    }
    return md;
}
protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
    MethodMetadata data = new MethodMetadata();
    data.targetType(targetType);
    data.method(method);
    data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));
    data.configKey(Feign.configKey(targetType, method));
    if(targetType.getInterfaces().length == 1) {
        this.processAnnotationOnClass(data, targetType.getInterfaces()[0]);
    }
    this.processAnnotationOnClass(data, targetType);
    Annotation[] parameterTypes = method.getAnnotations();
    int genericParameterTypes = parameterTypes.length;
    for(int parameterAnnotations = 0; parameterAnnotations < genericParameterTypes; ++parameterAnnotations) {
        Annotation count = parameterTypes[parameterAnnotations];
        //解析方法注解中的信息,如RequestMapping
        this.processAnnotationOnMethod(data, count, method);
    }
    if(data.isIgnored()) {
        return data;
    } else {
        Class[] var10 = method.getParameterTypes();
        Type[] var11 = method.getGenericParameterTypes();
        Annotation[][] var12 = method.getParameterAnnotations();
        int var13 = var12.length;
        for(int i = 0; i < var13; ++i) {
            boolean isHttpAnnotation = false;
            if(var12[i] != null) {
                //解析参数注解中的请求参数信息,如RequestParam
                isHttpAnnotation = this.processAnnotationsOnParameter(data, var12[i], i);
            }
            if(isHttpAnnotation) {
                data.ignoreParamater(i);
            }
            if(var10[i] == URI.class) {
                data.urlIndex(Integer.valueOf(i));
            } else if(!isHttpAnnotation && var10[i] != Options.class) {
                //没有在方法参数上使用注解,默认将参数保存到body中,后续get请求转为post也是这 
                 个原因导致的
                if(!data.isAlreadyProcessed(Integer.valueOf(i))) {
                    data.bodyIndex(Integer.valueOf(i));
                    data.bodyType(Types.resolve(targetType, targetType, var11[i]));
                } else {
                }
            }
        }
        if(data.headerMapIndex() != null) {
            checkMapString("HeaderMap", var10[data.headerMapIndex().intValue()], var11[data.headerMapIndex().intValue()]);
        }
        if(data.queryMapIndex() != null && Map.class.isAssignableFrom(var10[data.queryMapIndex().intValue()])) {
            checkMapKeys("QueryMap", var11[data.queryMapIndex().intValue()]);
        }
        return data;
    }
}
protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
    boolean isHttpAnnotation = false;
    SpringMvcContract.SimpleAnnotatedParameterContext context = new SpringMvcContract.SimpleAnnotatedParameterContext(data, paramIndex);
    Method method = (Method)this.processedMethods.get(data.configKey());
    Annotation[] typeDescriptor = annotations;
    int expander = annotations.length;

    for(int var9 = 0; var9 < expander; ++var9) {
        Annotation parameterAnnotation = typeDescriptor[var9];
        //获取注解对应的处理器,如RequestParam默认使用RequestParamParameterProcessor
        AnnotatedParameterProcessor processor = 
(AnnotatedParameterProcessor)this.annotatedArgumentProcessors.get(parameterAnnotation.annotationType());
        if(processor != null) {
            Annotation processParameterAnnotation = this.synthesizeWithMethodParameterNameAsFallbackValue(parameterAnnotation, method, paramIndex);
            //将请求参数保存到MethodMetadata的中,如RequestParam注解标注的参数会被保存到MethodMetadata的template的             
              queries变量中,get请求时将queries变量中的参数拼接到url上
            isHttpAnnotation |= processor.processArgument(context, processParameterAnnotation, method);
        }
    }
    if(!this.isMultipartFormData(data) && isHttpAnnotation && data.indexToExpander().get(Integer.valueOf(paramIndex)) == null) {
        TypeDescriptor var13 = createTypeDescriptor(method, paramIndex);
        if(this.conversionService.canConvert(var13, STRING_TYPE_DESCRIPTOR)) {
            Expander var14 = this.convertingExpanderFactory.getExpander(var13);
            if(var14 != null) {
                data.indexToExpander().put(Integer.valueOf(paramIndex), var14);
            }
        }
    }
    return isHttpAnnotation;
}

猜你喜欢

转载自blog.csdn.net/qq_33513289/article/details/108086652
今日推荐