美文网首页
说一说OpenFeign中的一工厂方法实现

说一说OpenFeign中的一工厂方法实现

作者: 天草二十六_简村人 | 来源:发表于2021-04-27 15:46 被阅读0次

    一、CachingSpringLoadBalancerFactory
    从类的名字也可以看出来,它是一个具备缓存功能和生成LB的工厂方法。
    除了构造函数,核心是create()方法了。
    1、缓存是通过ConcurrentReferenceHashMap集合实现,Key值clientName(被调用方的服务名),如果找到了,则返回。

    2、如果不存在,则调用组合类SpringClientFactory(也是一个工厂方法)的getClientConfig(clientName)和getLoadBalancer(clientName)「其实前两个方法也是由getInstance(String name, Class<C> type)实现」获取IClientConfig和ILoadBalancer。目的是创建FeignLoadBalancer的子类RetryableFeignLoadBalancer或者FeignLoadBalancer本身。

    client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
                loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
    
    // 其实下面三行代码的本质都是从应用上下文获取相应的对象。
    IClientConfig config = this.factory.getClientConfig(clientName);
            ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
            ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
    
    public <T> T getInstance(String name, Class<T> type) {
            AnnotationConfigApplicationContext context = getContext(name);
            if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
                    type).length > 0) {
                return context.getBean(type);
            }
            return null;
        }
    

    3、把创建好的FeignLoadBalancer对象放到集合缓存里。

    this.cache.put(clientName, client);
    
    

    下面是全部的详细源码

    package org.springframework.cloud.openfeign.ribbon;
    
    import java.util.Map;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
    import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
    import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
    import org.springframework.util.ConcurrentReferenceHashMap;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.ILoadBalancer;
    
    /**
     * Factory for SpringLoadBalancer instances that caches the entries created.
     *
     * @author Spencer Gibb
     * @author Dave Syer
     * @author Ryan Baxter
     * @author Gang Li
     */
    public class CachingSpringLoadBalancerFactory {
    
        private final SpringClientFactory factory;
        private LoadBalancedRetryFactory loadBalancedRetryFactory = null;
    
        private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
    
        public CachingSpringLoadBalancerFactory(SpringClientFactory factory) {
            this.factory = factory;
        }
    
        public CachingSpringLoadBalancerFactory(SpringClientFactory factory, LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
            this.factory = factory;
            this.loadBalancedRetryFactory = loadBalancedRetryPolicyFactory;
        }
    
        public FeignLoadBalancer create(String clientName) {
            FeignLoadBalancer client = this.cache.get(clientName);
            if(client != null) {
                return client;
            }
            IClientConfig config = this.factory.getClientConfig(clientName);
            ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
            ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
            client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
                loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
            this.cache.put(clientName, client);
            return client;
        }
    
    }
    

    二、几个问题
    1、值得参考的是它的cache属性的定义。

        private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
    

    一是它用volatile修饰,二是它采用了ConcurrentMap的一个子类。

    public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> 
    

    org.springframework.util.ConcurrentReferenceHashMap能指定所存放对象的引用级别,适用于并发下Map的数据缓存。

    在jvm满的时候,会回收掉不可达对象和软引用对象

    详细请参考
    https://cloud.tencent.com/developer/article/1633098?from=information.detail.concurrentreferencehashmap

    相关文章

      网友评论

          本文标题:说一说OpenFeign中的一工厂方法实现

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