51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Feign

<a name="HmTEj"></a>

1 先画一张图,借助feign调用接口的过程

2 Feign源码学习

学习Feign的突破入口应该在哪里?<br />第一个入口,启动类的注解@EnableFeignClients<br />第二个入口,我们自定义的接口的注解,@FeignClient<br />第二个入口的作用, 可以猜想到是由feign核心机制来扫描的,扫描到的接口,会生成动态代理,以及解析和处理接口上打的那些Spring web mvc 的注解,生成Http请求<br />同时也可以猜想到,第一个入口的注解,会触发对应的feign的核心机制,那个被触发的核心机制,会扫描所有包下面的被@FeignClient注解的接口。

@EnableFeignClients注解中,有@Import(FeignClientsRegistrar.class)<a name="q3loy"></a>

2.1 FeignClientsRegistrar

FeignClientsRegistrar实现了ImportBeanDefinationRegistrar接口,实现了以下方法<br />这个接口是Spring-context项目中带的。可以猜想的到,肯定是spring-boot启动时,spring容器初始化的时候,在某个时间点,会对实现这个接口的类的方法进行调用,来实例化一些bean,注册到spring容器中去。

@Override
public void registerBeanDefinations(AnnotationMetadate metadata,
                                   BeanDefinitionRegistry registry){
    //解析相关配置,注册到自己身体里面去
    registerDefaultConfiguration(metadata,registry);
    //扫描各个包下面的@FeignClient注解,生成动态代理
    registerFeignClients(metadata,registry);
}
public void registerFeignClients(AnnotationMetadata metadata,
                                BeanDefinitionRegistry registry){
    //获取一个组件扫描期
    ClassPathScannerCandidateComponentProvider scanner = getScanner();
    //从meta中获取EnableFeignClients注解的参数
    Map&lt;String,Object&gt; attrs = metadata.getAnnotationAttributes(
        						EnableFeignClients.class.getName());
    //...
    //生成一个只过滤FeignClient注解的过滤器
    AnnotationTypeFilter annotationTypeFilter = 
        new AnnotationTypeFilter(FeignClient.class);
    //从EnableFeignClients注解的参数中获取"clients",这是在指定那些被认为FeignClient
    //但是一般不设置,为空。Class&lt;?&gt;[] clients
    if(clients==null || clients.length == 0) {
        //组件扫描器和过滤器关联
        scanner.addIncluderFilter(annotationTypeFilter);
        //根据元数据获取药扫描的包
        basePackages = getBasePackages(metadata);
    }
    for(String basePackage : basePackages){
        //从packages中找到候选的组件
        Set&lt;BeanDifinition&gt;candidateComponents = 
            scanner.findCandidateComponents(basePackages);
        //
    }
    
}
protected Set&lt;String&gt; getBasePackages(AnnotationMetadata importingClassMetadata){
    Set&lt;String&gt; basePackages;
    //获取元数据
    //如果元数据中配了value\basePackages\basePackageClasses,
	//则转换为包路径,添加到basePackages中
	//如果还是为空,则把@EnableFeignClients注解所在包
	//(也就是Application启动类所在包)的路径加进来
	//比如com.zhss.services
	if(basePackages.isEmpty()){
        basePackages.add(
            ClassUtils.getPackageName(importingClassMetadata.getClassName()));
    }
}
赞(9)
未经允许不得转载:工具盒子 » Feign