Feign源码解析之代理类的处理逻辑

Feign源码解析之注入IOC容器
Feign源码解析之生成jdk动态代理

上面两篇文章分析了在springboot中feign是如何注入IOC容器并生成jdk动态代理类的,下面我们将着重分析一下feign的代理类的处理逻辑,看一看代理类是如何将接口里的方法转化成http请求的。
之前的文章有提到,在通过FeignClientFactoryBean的getObject方法生成代理类的过程中是根据applicationContext和配置文件获取到其中的属性值的,因此我们可以通过将特定类注入IOC容器或者修改配置的方式实现自定义的实现方式。所以,在文章开始之前首先声明,下文中的分析全部基于springboot中的feign的默认实现。

一. Feign的配置类
首先,feign在springboot中主要有两个配置类,其中的自动配置类FeignAutoConfiguration在之前的文章中已经有提到,下面我们了解一下另一个配置类FeignClientsConfiguration,这个类是在FeignContext的父类方法createContext中的context.register(PropertyPlaceholderAutoConfiguration.class,this.defaultConfigType);语句注入各个client所属的applicationContext中的。

@Configuration
public class FeignClientsConfiguration {

	@Autowired
	private ObjectFactory<HttpMessageConverters> messageConverters;

	@Autowired(required = false)
	private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>();

	@Autowired(required = false)
	private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>();

	@Autowired(required = false)
	private Logger logger;

	@Bean
	@ConditionalOnMissingBean
	public Decoder feignDecoder() {
		return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
	}

	@Bean
	@ConditionalOnMissingBean
	public Encoder feignEncoder() {
		return new SpringEncoder(this.messageConverters);
	}

	@Bean
	@ConditionalOnMissingBean
	public Contract feignContract(ConversionService feignConversionService) {
		return new SpringMvcContract(this.parameterProcessors, feignConversionService);
	}

	@Bean
	public FormattingConversionService feignConversionService() {
		FormattingConversionService conversionService = new DefaultFormattingConversionService();
		for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) {
			feignFormatterRegistrar.registerFormatters(conversionService);
		}
		return conversionService;
	}

	@Configuration
	@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
	protected static class HystrixFeignConfiguration {
		@Bean
		@Scope("prototype")
		@ConditionalOnMissingBean
		@ConditionalOnProperty(name = "feign.hystrix.enabled")
		public Feign.Builder feignHystrixBuilder() {
			return HystrixFeign.builder();
		}
	}

	@Bean
	@ConditionalOnMissingBean
	public Retryer feignRetryer() {
		return Retryer.NEVER_RETRY;
	}

	@Bean
	@Scope("prototype")
	@ConditionalOnMissingBean
	public Feign.Builder feignBuilder(Retryer retryer) {
		return Feign.builder().retryer(retryer);
	}

	@Bean
	@ConditionalOnMissingBean(FeignLoggerFactory.class)
	public FeignLoggerFactory feignLoggerFactory() {
		return new DefaultFeignLoggerFactory(logger);
	}
}

FeignClientsConfiguratiob中注入的几个类都是在生成并使用代理类过程中的属性的默认值。

二. FeignInvocationHandler类的invoke方法
接着我们继续看动态类的执行方法:FeignInvocationHandler类的invoke方法,可以发现其执行逻辑为从dispatch中根据method获取到对应的methodHandle以执行invoke方法。

@Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   if ("equals".equals(method.getName())) {
     try {
       Object
           otherHandler =
           args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
       return equals(otherHandler);
     } catch (IllegalArgumentException e) {
       return false;
     }
   } else if ("hashCode".equals(method.getName())) {
     return hashCode();
   } else if ("toString".equals(method.getName())) {
     return toString();
   }
   return dispatch.get(method).invoke(args);
 }

由于dispatch属性是由ReflectiveFeign类调用FeignInvocationHandle的构造方法时传入的,我们需要进入ReflectiveFeign的newInstance方法关注dispatch的值。

public <T> T newInstance(Target<T> target) {
  Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
  Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
  List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();

  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)));
    }
  }
  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;
}

局部变量methodToHandler即传入FeignInvocationHandle的dispatch属性,遍历feignClient接口的方法进行组装,分3中情况:
1.从object类继承而来的方法,忽略。这一点也和FeignInvocationHandle的invoke方法针对equal、hashcode、toString方法的处理吻合。
2.接口中的default方法,对应的methodHandle的逻辑依旧还是原方法的逻辑
3.其它方法ÿ

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值