spring cloud openfeign 源码实例解析
一、读取注解信息
入口
importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients publicclassCjsPriceServiceApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(CjsPriceServiceApplication.class,args); } }
springboot项目启动后会自动扫描application上面的注解,@EnableFeignClients的注解如下
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(FeignClientsRegistrar.class) public@interfaceEnableFeignClients{ 。。。。 }
在注解中导入了FeignClientsRegistrar类,用来像spring注册,EnableFeignClients和FeignClient上面开发人员添加的注解信息
@Override publicvoidregisterBeanDefinitions(AnnotationMetadatametadata, BeanDefinitionRegistryregistry){ registerDefaultConfiguration(metadata,registry); registerFeignClients(metadata,registry); }
二、当项目启动,读取@Autowired时会调用,实现了FactoryBean接口的FeignClientFactoryBean.getObject()方法
@Override publicObjectgetObject()throwsException{ returngetTarget(); }
TgetTarget(){ FeignContextcontext=this.applicationContext.getBean(FeignContext.class); Feign.Builderbuilder=feign(context); if(!StringUtils.hasText(this.url)){ if(!this.name.startsWith("http")){ this.url="http://"+this.name; } else{ this.url=this.name; } this.url+=cleanPath(); return(T)loadBalance(builder,context, newHardCodedTarget<>(this.type,this.name,this.url)); } if(StringUtils.hasText(this.url)&&!this.url.startsWith("http")){ this.url="http://"+this.url; } Stringurl=this.url+cleanPath(); Clientclient=getOptional(context,Client.class); if(client!=null){ if(clientinstanceofLoadBalancerFeignClient){ //notloadbalancingbecausewehaveaurl, //butribbonisontheclasspath,sounwrap client=((LoadBalancerFeignClient)client).getDelegate(); } builder.client(client); } Targetertargeter=get(context,Targeter.class); return(T)targeter.target(this,builder,context, newHardCodedTarget<>(this.type,this.name,url)); }
可以看到getTarget()有两种返回结果的情况,其原理都一样后来调用了targeter.target()方法
packageorg.springframework.cloud.openfeign; importfeign.Feign; importfeign.Target; /** *@authorSpencerGibb */ interfaceTargeter{Ttarget(FeignClientFactoryBeanfactory,Feign.Builderfeign, FeignContextcontext,Target.HardCodedTarget target); }
默认实现类
packageorg.springframework.cloud.openfeign; importfeign.Feign; importfeign.Target; /** *@authorSpencerGibb */ classDefaultTargeterimplementsTargeter{ @Override publicTtarget(FeignClientFactoryBeanfactory,Feign.Builderfeign, FeignContextcontext,Target.HardCodedTarget target){ returnfeign.target(target); } }
然后再看feign.target(target);方法
publicTtarget(Target target){ returnbuild().newInstance(target); } publicFeignbuild(){ SynchronousMethodHandler.FactorysynchronousMethodHandlerFactory= newSynchronousMethodHandler.Factory(client,retryer,requestInterceptors,logger, logLevel,decode404,closeAfterDecode,propagationPolicy); ParseHandlersByNamehandlersByName= newParseHandlersByName(contract,options,encoder,decoder,queryMapEncoder, errorDecoder,synchronousMethodHandlerFactory); returnnewReflectiveFeign(handlersByName,invocationHandlerFactory,queryMapEncoder); } }
build()方法返回了创建代理类的对象,然后调用了创建代理的newInstance方法
publicTnewInstance(Target target){ Map nameToHandler=targetToHandlersByName.apply(target); Map methodToHandler=newLinkedHashMap (); List defaultMethodHandlers=newLinkedList (); for(Methodmethod:target.type().getMethods()){ if(method.getDeclaringClass()==Object.class){ continue; }elseif(Util.isDefault(method)){ DefaultMethodHandlerhandler=newDefaultMethodHandler(method); defaultMethodHandlers.add(handler); methodToHandler.put(method,handler); }else{ methodToHandler.put(method,nameToHandler.get(Feign.configKey(target.type(),method))); } } InvocationHandlerhandler=factory.create(target,methodToHandler); Tproxy=(T)Proxy.newProxyInstance(target.type().getClassLoader(), newClass>[]{target.type()},handler); for(DefaultMethodHandlerdefaultMethodHandler:defaultMethodHandlers){ defaultMethodHandler.bindTo(proxy); } returnproxy; }
最后,当我们项目中使用@Autowired注入时,就回调用工厂类FeignClientFactoryBean方法的getObject()方法返回我们的代理对象
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。