说一说OpenFeign中的一工厂方法实现
2021-04-27 本文已影响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满的时候,会回收掉不可达对象和软引用对象