Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Spring-cloud Feign

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article shares with you the content of the sample analysis of Spring-cloud Feign. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

The calling process of feign

Read comment information: EnableFeignClients-- > FeignClientsRegistrar-- > FeignClientFactoryBean

Feigh process: ReflectiveFeign-- > Contract-- > SynchronousMethodHandler

Related configuration:FeignClientsConfiguration,FeignAutoConfiguration,DefaultFeignLoadBalancedConfiguration,FeignRibbonClientAutoConfiguration (Ribbon)

In FeignClientsRegistrar:

@ Override public void registerBeanDefinitions (AnnotationMetadata metadata, BeanDefinitionRegistry registry) {/ / register feign configuration information registerDefaultConfiguration (metadata, registry); / / register feign client registerFeignClients (metadata, registry);} private void registerFeignClient (BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map attributes) {String className = annotationMetadata.getClassName (); / / prepare to inject FeignClientFactoryBean BeanDefinitionBuilder definition = BeanDefinitionBuilder .genericBeanDefinition (FeignClientFactoryBean.class);...}

View FeignClientFactoryBean:

@ Override public Object getObject () throws Exception {FeignContext context = applicationContext.getBean (FeignContext.class); / / build Feign.Builder Feign.Builder builder = feign (context); / / if the annotation does not specify URL if (! StringUtils.hasText (this.url)) {String url; if (! this.name.startsWith ("http")) {url = "http://" + this.name" } else {url = this.name;} url + = cleanPath (); return loadBalance (builder, context, new HardCodedTarget (this.type, this.name, url));} / / if URL if (StringUtils.hasText (this.url) & &! this.url.startsWith ("http") is specified) {this.url = "http://" + this.url" } String url = this.url + cleanPath (); Client client = getOptional (context, Client.class); if (client! = null) {if (client instanceof LoadBalancerFeignClient) {/ / because URL is specified and there is Ribbon under classpath, get delegate (unwrap) / / not load balancing because we have a url, / / but ribbon is on the classpath, so unwrap client = (LoadBalancerFeignClient) client. GetDelegate () of client } builder.client (client);} Targeter targeter = get (context, Targeter.class); return targeter.target (this, builder, context, new HardCodedTarget (this.type, this.name, url));} protected T loadBalance (Feign.Builder builder, FeignContext context, HardCodedTarget target) {/ / get Feign Client instance Client client = getOptional (context, Client.class); if (client! = null) {builder.client (client) / / DefaultTargeter or HystrixTargeter Targeter targeter = get (context, Targeter.class); / / call builder's target, where Feign's newInstance return targeter.target (this, builder, context, target) is called;} throw new IllegalStateException ("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon? ");}

The Feign.Builder,prototype type is configured in FeignClientsConfiguration:

@ Bean @ Scope ("prototype") @ ConditionalOnMissingBean public Feign.Builder feignBuilder (Retryer retryer) {return Feign.builder () .retryer (retryer);}

The Builder.build of Feign returns a ReflectiveFeign:

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 construction parameter / / ParseHandlersByName function is to return all kinds of information of the method under the proxy interface through the passed target (MethodHandler) / / Contract: parse the method annotation rules of the interface Generate MethodMetadata / / Options:Request timeout configuration / / Encoder: request encoder / / Decoder: return decoder / / ErrorDecoder: error decoder / / SynchronousMethodHandler.Factory is the factory for building SynchronousMethodHandler / / Client: represents the component that actually executes HTTP / / Retryer: this group determines whether to retry if the http request fails / / RequestInterceptor: interceptor before request / / Logger: logging component Contains the logging method for each stage and the log method / / Logger.Level: log level / / decode404: handle the policy, return null or error / / synchronousMethodHandlerFactory wraps a synchronousMethodHandler with all the information, and executes HTTP return new ReflectiveFeign (handlersByName, invocationHandlerFactory) when the invoke method is called }

When the target of Feign.Builder is called, ReflectiveFeign.newInstance is called:

/ * * creates an api binding to the {@ code target}. As this invokes reflection, care should be taken * to cache the result. * / @ SuppressWarnings ("unchecked") @ Override / / receives the Target parameter (including the type class, name, http URL of the feign proxy interface) public T newInstance (Target target) {/ / first parses the method contained in the interface through * * ParseHandlersByName**, wraps RequestTemplate, and assembles it into Map nameToHandler = targetToHandlersByName.apply (target); Map methodToHandler = new LinkedHashMap (); / / Interface default method List 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 {methodToHandler.put (method, nameToHandler.get (Feign.configKey (target.type (), method) }} / / InvocationHandlerFactory.Default () returns a ReflectiveFeign.FeignInvocationHandler object, calling the corresponding method InvocationHandler handler = factory.create (target, methodToHandler) of the target object through the passed methodHandler map; / / generating the JDK proxy object T proxy = (T) Proxy.newProxyInstance (target.type (). GetClassLoader (), new Class [] {target.type ()}, handler) / / bind the default method of the interface to proxy object for (DefaultMethodHandler defaultMethodHandler: defaultMethodHandlers) {defaultMethodHandler.bindTo (proxy);} return proxy;}

Generate a basic flowchart of the Feign proxy object:

When you call an interface method, you are actually calling the proxy object invoke method:

@ Override public Object invoke (Object [] argv) throws Throwable {/ / Factory creation request template RequestTemplate template = buildTemplateFromArgs.create (argv); / / Clone a new Retryer Retryer retryer = this.retryer.clone () at a time; while (true) {try {/ / call the actual Feign client execute return executeAndDecode (template) here;} catch (RetryableException e) {/ / failed retry retryer.continueOrPropagate (e) If (logLevel! = Logger.Level.NONE) {logger.logRetry (metadata.configKey (), logLevel);} continue;}

LoadBalancerFeignClient is instantiated in DefaultFeignLoadBalancedConfiguration

@ Override public Response execute (Request request, Request.Options options) throws IOException {try {URI asUri = URI.create (request.url ()); String clientName = asUri.getHost (); URI uriWithoutHost = cleanUrl (request.url (), clientName); / / delegate here is the Client.Default instance, and the underlying call is java.net native network access FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest (this.delegate, request, uriWithoutHost) IClientConfig requestConfig = getClientConfig (options, clientName); / / executeWithLoadBalancer will build url based on ribbon's load balancing algorithm. Here return lbClient (clientName) .executeWithLoadBalancer (ribbonRequest, requestConfig). ToResponse ();} catch (ClientException e) {IOException io = findIOException (e); if (io! = null) {throw io;} throw new RuntimeException (e) Thank you for your reading! This is the end of this article on "sample Analysis of Spring-cloud Feign". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report