当我们在使用的时候首先启用Feign,即 启动类中添加注解@EnableFeignClients
@EnableFeignClients
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
进入@EnableFeignClients注解类中
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
}
关于@Import的使用可以查看@Import注解了解,此处加载FeignClientsRegistrar类,我们可以继续进入该类中
class FeignClientsRegistrar
implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
}
FeignClientsRegistrar有多个接口实现,ImportBeanDefinitionRegistrar用于自定义实现Bean定义信息、ResourceLoaderAware、EnvironmentAware
我们重点看下ImportBeanDefinitionRegistrar的接口方法registerBeanDefinitions的实现
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}
其中registerDefaultConfiguration(metadata, registry);方法主要是获取@EnableFeignClients注解参数defaultConfiguration的值…
我们重点看下registerFeignClients(metadata, registry);
public void registerFeignClients(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
LinkedHashSet candidateComponents = new LinkedHashSet<>();
//获取注解中的属性信息
Map attrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName());
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
FeignClient.class);
final Class>[] clients = attrs == null ? null
: (Class>[]) attrs.get("clients");
//如果没有clients配置信息,则取获取所有@FeignClient 标注的类
if (clients == null || clients.length == 0) {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
//存放被@FeignClient标注的类的定义信息(BeanDefinition)
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
}
//如果有指定的clients信息 会走到该逻辑
else {
for (Class> clazz : clients) {
candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
}
}
//循环遍历@FeignClient标注的类的BeanDefinition
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
//验证带注解的类是否为接口
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
//获取@FeignClient的属性信息
Map attributes = annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());
//获取名称
String name = getClientName(attributes);
//将一些配置信息添加到 registry的BeanDefinition集合中(编码器、解码器等)
registerClientConfiguration(registry, name,
attributes.get("configuration"));
//注册FeignClient
registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
我们还是重点关注下registerFeignClient方法的调用,我们需要重点留意下 有设置 FeignClientFactoryBean(表示注册的FeignClient都是FeignClientFactoryBean类型的)
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Mapattributes) { //获取当前被@FeignClient标注的类名 String className = annotationMetadata.getClassName(); //通过建造者模式创建BeanDefinition //BeanDefinitionBuilder中含有属性beanDefinition(GenericBeanDefinition类型) //beanDefinition设置beanClass(Class类型)为FeignClientFactoryBean.class **BeanDefinitionBuilder definition = BeanDefinitionBuilder .genericBeanDefinition(FeignClientFactoryBean.class);** validate(attributes); definition.addPropertyValue("url", getUrl(attributes)); definition.addPropertyValue("path", getPath(attributes)); String name = getName(attributes); definition.addPropertyValue("name", name); String contextId = getContextId(attributes); definition.addPropertyValue("contextId", contextId); definition.addPropertyValue("type", className); definition.addPropertyValue("decode404", attributes.get("decode404")); definition.addPropertyValue("fallback", attributes.get("fallback")); definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory")); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); String alias = contextId + "FeignClient"; AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className); // has a default, won't be null boolean primary = (Boolean) attributes.get("primary"); beanDefinition.setPrimary(primary); String qualifier = getQualifier(attributes); if (StringUtils.hasText(qualifier)) { alias = qualifier; } //创建BeanDefinitionHolder BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias }); //注册FeignClient的BeanDefinition信息 BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); }
我们继续重点看下BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);方法
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
//注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
关于调用流程
假设我们有一个IRemoteCallService类
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name="server-user")
public interface IRemoteCallService {
@RequestMapping(value="/user/getNameById",method = RequestMethod.POST)
String getName(@RequestParam("userId") String userId);
}
当我们执行context.getBean(IRemoteCallService.class);时
@EnableFeignClients
public class GatewayApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(GatewayApplication.class, args);
IRemoteCallService bean = context.getBean(IRemoteCallService.class);
}
}
中间具体细节调用流程为:
org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class)
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class)
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class, java.lang.Object…)
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class, java.lang.Object…)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
我们看下doGetBean中部分方法:
protectedT doGetBean( String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } }
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//mbd 是 GenericBeanDefinition转化而来的
RootBeanDefinition mbdToUse = mbd;
//获得beanClass,即:FeignClientFactoryBean
Class> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//可以通过调用BeanPostProcessors来完成实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
try {
//调用doCreateBean方法,
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}
我们继续看下 doCreateBean方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...
}
createBeanInstance方法调用
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//beanClass :FeignClientFactoryBean
Class> beanClass = resolveBeanClass(mbd, beanName);
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
//调用构造方法实例化
return instantiateBean(beanName, mbd);
}
我们继续返回到doGetBean方法中,调用完createBean方法后,继续调用getObjectForBeanInstance方法
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//此时我们拿到的 beanInstance 是 FeignClientFactoryBean的实例,FeignClientFactoryBean是实现了FactoryBean接口的
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//获取缓存
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean> factory = (FactoryBean>) beanInstance;
// 缓存获取Bean定义信息
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//获取Object
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
else {
//调用doGetObjectFromFactoryBean方法
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(FactoryBean> factory, String beanName) throws BeanCreationException {
Object object;
try {
else {
//调用FeignClientFactoryBean的getObject方法
object = factory.getObject();
}
}
}
关于代理创建流程
org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject
@Override
public Object getObject() throws Exception {
return getTarget();
}
T getTarget() { //获取FeignClientSpecification中存放的配置信息(编码器、解码器) FeignContext context = applicationContext.getBean(FeignContext.class); Feign.Builder builder = feign(context); //组装url,(http://server-user) if (!StringUtils.hasText(url)) { if (!name.startsWith("http")) { url = "http://" + name; } else { url = name; } url += cleanPath(); return (T) loadBalance(builder, context, new HardCodedTarget<>(type, name, url)); } if (StringUtils.hasText(url) && !url.startsWith("http")) { url = "http://" + url; } String url = this.url + cleanPath(); Client client = getOptional(context, Client.class); if (client != null) { if (client instanceof LoadBalancerFeignClient) { client = ((LoadBalancerFeignClient) client).getDelegate(); } if (client instanceof FeignBlockingLoadBalancerClient) { client = ((FeignBlockingLoadBalancerClient) client).getDelegate(); } builder.client(client); } // Targeter targeter = get(context, Targeter.class); //生成代理 return (T) targeter.target(this, builder, context, new HardCodedTarget<>(type, name, url)); }
调用org.springframework.cloud.openfeign.DefaultTargeter#target
@Override publicT target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, Target.HardCodedTarget target) { return feign.target(target); }
调用 feign.Feign.Builder#target(feign.Target)
publicT target(Target target) { return build().newInstance(target); }
调用 feign.Feign.Builder#build
private InvocationHandlerFactory invocationHandlerFactory = new InvocationHandlerFactory.Default();
public Feign build() {
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404);
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder,
errorDecoder, synchronousMethodHandlerFactory);
//生成ReflectiveFeign,
return new ReflectiveFeign(handlersByName, invocationHandlerFactory);
}
返回到feign.Feign.Builder#target(feign.Target),继续看newInstance方法调用
@Override publicT newInstance(Target target) { //调用targetToHandlersByName.apply,对该FeignClient中所有的方法生成 MethodHandler (SynchronousMethodHandler类型) Map nameToHandler = targetToHandlersByName.apply(target); Map methodToHandler = new LinkedHashMap (); List defaultMethodHandlers = new LinkedList (); //遍历所有的 方法 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 { //将FeignClient中方法和对应的MethodHandler 保存起来 //nameToHandler 保存的是 基于类名方法名等信息和对应的MethodHandler的集合信息 //methodToHandler保存的是method类与对应的MethodHandler的集合信息 methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method))); } } //生成 handler (FeignInvocationHandler类型),含有两个属性target即 FeignClient对应的类,dispatch即类中方法和对应的MethodHandler(SynchronousMethodHandler类型) InvocationHandler handler = factory.create(target, methodToHandler); //基于Proxy生成JDK动态代理 T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class>[]{target.type()}, handler); for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) { defaultMethodHandler.bindTo(proxy); } //返回代理对象 return proxy; }
targetToHandlersByName.apply的调用
public Map关于代理调用流程apply(Target key) { List metadata = contract.parseAndValidatateMetadata(key.type()); Map result = new LinkedHashMap (); for (MethodMetadata md : metadata) { BuildTemplateByResolvingArgs buildTemplate; if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) { buildTemplate = new BuildFormEncodedTemplateFromArgs(md, encoder); } else if (md.bodyIndex() != null) { buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder); } else { buildTemplate = new BuildTemplateByResolvingArgs(md); } result.put(md.configKey(), factory.create(key, md, buildTemplate, options, decoder, errorDecoder)); } return result; }
上面我们清楚了代理中生成的 handler (FeignInvocationHandler类型),含有两个属性target即 FeignClient对应的类,dispatch即类中方法和对应的MethodHandler(SynchronousMethodHandler类型)
1、我们看下 FeignInvocationHandler的具体调用流程
feign.ReflectiveFeign.FeignInvocationHandler#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();
}
//基于dispatch 找到对应的 MethodHandler,调用invoke方法
return dispatch.get(method).invoke(args);
}
2、我们看下 SynchronousMethodHandler的具体调用流程
@Override
public Object invoke(Object[] argv) throws Throwable {
//基于参数构建RequestTemplate
RequestTemplate template = buildTemplateFromArgs.create(argv);
//克隆重试机制的类
Retryer retryer = this.retryer.clone();
while (true) {
try {
//执行调用和解码工作
return executeAndDecode(template);
} catch (RetryableException e) {
retryer.continueOrPropagate(e);
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
Object executeAndDecode(RequestTemplate template) throws Throwable {
//获取Request对象
//此处也是自定义拦截器的实现
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
//通过client进行发起
response = client.execute(request, options);
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
boolean shouldClose = true;
try {
if (logLevel != Logger.Level.NONE) {
response =
logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
}
//
if (Response.class == metadata.returnType()) {
if (response.body() == null) {
return response;
}
if (response.body().length() == null ||
response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
shouldClose = false;
return response;
}
// Ensure the response body is disconnected
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
return Response.create(response.status(), response.reason(), response.headers(), bodyData);
}
//成功进行解码返回
if (response.status() >= 200 && response.status() < 300) {
if (void.class == metadata.returnType()) {
return null;
} else {
return decode(response);
}
} else if (decode404 && response.status() == 404) {
return decoder.decode(response, metadata.returnType());
} else {
throw errorDecoder.decode(metadata.configKey(), response);
}
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);
}
throw errorReading(request, response, e);
} finally {
if (shouldClose) {
//响应流关闭
ensureClosed(response.body());
}
}
}
关于一些核心的类的定义可以查看链接来学习
操作实例可查看feign自定义请求拦截器、编码器、解码器
OpenFeign拦截器RequestInterceptor的使用



