SpringCloudOpenFeign

feign
  • feign是一个远程客户端
  • 他的核心是feignclient,内部实际上是一个动态代理,把requestMapping上的地址 拼接成目标地址
Feign要做的事情
  • 参数的解析和装载
  • 针对指定的feignClient,生成动态代理
  • 针对FeignClient中的方法描述进行解析
  • 组装出一个Request对象,发起请求
Bean的动态装载

所有实现了该接口的类的都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化,也能被aop、validator等机制处理。

基本步骤:

实现ImportBeanDefinitionRegistrar接口;
通过registerBeanDefinitions实现具体的类初始化;
在@Configuration注解的配置类上使用@Import导入实现类;

  • ImportSelector
  • ImportBeanDefinitionRegistrar
例子:
  • 定义一个测试类
public class HelloService {

}
  • 定义ImportBeanDefinitionRegistrar的实现类
public class JimImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClassName(HelloService.class.getName());
        registry.registerBeanDefinition("helloService",beanDefinition);
    }
}
  • 自定义一个注解,注解中@Import进去自定义实现类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(JimImportBeanDefinitionRegistrar.class)
public @interface EnableJimRegistrara {
}

  • 测试
@SpringBootApplication
@EnableJimRegistrara
@ComponentScan(basePackages = {"com.exercise.eg.feign.demo"})

public class FeignApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(FeignApplication.class, args);
        System.out.println(context.getBean(HelloService.class));
        System.out.println(context.getBean("helloService"));
    }
}
再看Feign 的@EnableFeignClients里面的FeignClientsRegistrar.class
@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //注册@EnableFeignClients中定义defaultConfiguration属性下的类,包装成 FeignClientSpecification,注册到Spring容器。 //在@FeignClient中有一个属性:configuration,这个属性是表示各个FeignClient自定义的配 置类,后面也会通过调用registerClientConfiguration方法来注册成FeignClientSpecification 到容器。 //所以,这里可以完全理解在@EnableFeignClients中配置的是做为兜底的配置,在各个@FeignClient 配置的就是自定义的情况。 registerDefaultConfiguration(metadata, registry); registerFeignClients(metadata, registry); }

registerFeignClients 这个方法主要是扫描类路径下所有的@FeignClient注解,然后进行动态Bean的注入。它最终会调用 registerFeignClient 方法
Spring Cloud FengnClient实际上是利用Spring的代理工厂来生成代理类,所以在这里地方才会 把所有的FeignClient的BeanDefinition设置为FeignClientFactoryBean类型,而 FeignClientFactoryBean继承自FactoryBean,它是一个工厂Bean。 在Spring中,FactoryBean是一个工厂Bean,用来创建代理Bean。 工厂 Bean 是一种特殊的 Bean, 对于 Bean 的消费者来说, 他逻辑上是感知不到这个 Bean 是普 通的 Bean 还是工厂 Bean, 只是按照正常的获取 Bean 方式去调用, 但工厂bean 最后返回的实 例不是工厂Bean 本身, 而是执行工厂 Bean 的 getObject 逻辑返回的实例。

public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) { BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition()); builder.beanDefinition.setBeanClass(beanClass); return builder; }

简单来说,FeignClient标注的这个接口,会通过FeignClientFactoryBean.getObject()这个方法获得一
个代理对象。

分析FeignClientFactoryBean.getObject
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值