美文网首页
动态代理在Feign中的应用

动态代理在Feign中的应用

作者: 鸿雁长飞鱼龙潜跃 | 来源:发表于2019-08-09 17:50 被阅读0次

    一,动态代理可以做什么

    动态代理可以在不修改源代码的前提下,对目标方法进行增强。

    二,动态代理的核心要素


    1,Proxy.newProxyInstance():生成代理类

    static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

    入参含义如下:

    loader:目标对象的类加载器。作用是让这个方法的一个类加载运行起来,创建我们需要的代理对象。源码注释如下:the class loader to define the proxy class.

    interfaces:接口,类型是Class数组。目标对象的接口类型数组。作用是让代理对象知道,目标对象实现了哪些接口,代理对象就去实现这些接口。源码注释如下:the list of interfaces for the proxy to implement.

    h:回调处理者。作用是把调用转发给代理类,也就是转发给InvocationHandler.invoke()。

    源码注释如下:the invocation handler to dispatch method invacations to.

    2,InvocationHandler.invoke():回调处理者,作用就是接收MethodHandler.invoke()转发过来的请求,交给代理类的具体方法进行处理。

    InvocationHandler是一个接口,官方注释如下:InvocationHandler is the interface implenented by the invocation handler of a proxy interface.

    翻译过来就是:代理类的回调处理者,需要实现InvocationHandler接口。

    public Object invoke(Object proxy, Method method, Object[] args)

    注意:不要手动调用该方法

    入参含义如下:

    proxy:代理对象本身。

    method:拦截到的方法。

    args: 代理对象调用方法时传递的参数。

    3,MethodHandler.invoke()

    具体的代理执行逻辑。

    四,Feign发送请求实现原理

    微服务启动类上标记@EnableFeignClients注解,然后Feign接口上标记@FeignClient注解。@FeignClient注解有几个参数需要配置,这里不再赘述,都很简单。

    Feign框架会扫描注解,然后通过Feign类来处理注解,并最终生成一个Feign对象。

    1,解析@FeignClient注解,生成MethodHandler

    具体的解析类是ParseHandlerByName。这个类是ReflectiveFeign的内部类。

    // 解析注解元数据,使用Contract解析

    List<MethodMetadata> metadata = this.contract.parseAndValidateMetadata(key.type());

    拿到注解元数据以后,循环处理注解元数据,创建每个方法对应的MethodHandler,这个MethodHandler最终会被代理对象调用。最终MethodHandler都会保存到下面这个集合中,然后返回。

    Map<String, MethodHandler> result = new LinkedHashMap();

    2,解析完成以后,调用ReflectiveFeign.newInstance()生成代理类。

    MethodHandler是feign的一个接口,这个接口的invoke方法,是动态代理调用者InvocationHandler的invoke()方法最终调用的方法。

    重新表述一遍:InvocationHandler的invoke()方法最终接收MethodHandler的invoke()来发送http请求。这就是Feign动态代理的具体实现。

    ReflectiveFeign类的newInstance()方法的第57行:

    // 创建动态代理调用者

    InvocationHandler handler = this.factory.create(target, methodToHandler);

    // 反射生成feign接口代理

    T proxy = Proxy.newProxyInstance(加载器, 接口数组, handler);

    InvocationHandler.invoke()的具体实现在FeignInvocationHandler.invoke(),FeignInvocationHandler也是ReflectiveFeign的一个内部类。里面有很多细节处理这里不再赘述,我们直接进入核心那一行代码,以免影响思路,我们是理Feign的实现原理的!不要在意这些细节!

    // InvocationHandler的invoke()方法最终回调MethodHandler的invoke()来发送http请求

    ReflectiveFeign类的invoke()方法,第323行,代码的后半段,如下:

    (MethodHandler)this.dispatch.get(method). invoke(args);

    这行伟大的代码,我们来仔细分析一下!

    this.dispatch:这是一个map,就是保存所有的MethodHandler的集合。参考创建InvocationHandler的位置:ReflectiveFeign类的newInstance()方法的第57行。

    this.dispatch.get(method):这里的method就是我们开发者写的feign接口中定义的方法的方法名!这段代码的意思就是从MethodHandler集合中拿到我们需要调用的那个方法。

    this.dispatch.get(method). invoke(args):这里的invoke就是调用的MethodHandler.invoke()!动态代理回调代理类,就这样完成了,oh my god,多么伟大的创举!

    3,MethodHandler.invoke()的具体实现:SynchronousMethodHandler.invoke()

    到了这里,就是发送请求的逻辑了。发送请求前,首先要创建请求模板,然后调用请求拦截器RequestInterceptor进行请求处理。

    // 创建RequestTemplate

    RequestTemplate template = this.buildTemlpateFromArgs.create(argv);

    // 创建feign重试器,进行失败重试

    Retryer retryer = this.retryer.clone();

    while(true){

        try{

            // 发送请求

            return this.executeAndDecode(template);

        } catch(RetryableException var5) {

            // 失败重试,最多重试5次

            retryer.continueOrPropagate();

        }

    }

    五,总结

    动态代理在feign中的应用。

    动态代理在Feign中的应用

    Feign架构图

    动态代理在Feign中的应用

    相关文章

      网友评论

          本文标题:动态代理在Feign中的应用

          本文链接:https://www.haomeiwen.com/subject/vdtkjctx.html