1. 启动

feign 通过使用 注解 org.springframework.cloud.openfeign.EnableFeignClients
传入 feign 客户端接口所在的包

如下:

@Configuration
@EnableFeignClients("cn.coollf.cloud.member.api")
public class ClientAutoConfiguration 

真正工作的是

@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()
通过spring boot的 @Import 标签 来引入 FeignClientsRegistrar

FeignClientsRegistrar 类实现了 ImportBeanDefinitionRegistrar , 实现该接口的类拥有注册bean的能力, spring boot 在启动时 会调用
org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)

来让 ImportBeanDefinitionRegistrar 子类进行 bean的定义和注册

FeignClientsRegistrar 在

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients

方法中获取EnableFeignClients注解传入的包明获取该包明下的子包,
然后

为每一个有注解 @FeignClient 的接口 注册一个 beanDefinition

    private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
        String className = annotationMetadata.getClassName();
        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.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();
        boolean primary = (Boolean)attributes.get("primary");
        beanDefinition.setPrimary(primary);
        String qualifier = this.getQualifier(attributes);
        if (StringUtils.hasText(qualifier)) {
            alias = qualifier;
        }

        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
    }

所以生成 我们定义的 @FeignClient 接口的是实现类是由 FeignClientFactoryBean 来生成的

org.springframework.cloud.openfeign.FeignClientFactoryBean#getTarget
通过这个方法来返回一个 实现了我们定义的 Client 接口的的代理类, 通过这个类来实现
Feign的调用

我们调用实现类的方法时会被
feign.ReflectiveFeign.FeignInvocationHandler#FeignInvocationHandler
这个拦截器捕获, 由这个拦截来 方法任务到 feign.SynchronousMethodHandler 类 来进行底层方法的操作 进行 http 的远程调用