千家信息网

spring cloud中FeignClientFactoryBean的原理和作用是什么

发表于:2024-12-03 作者:千家信息网编辑
千家信息网最后更新 2024年12月03日,这篇文章主要介绍"spring cloud中FeignClientFactoryBean的原理和作用是什么",在日常操作中,相信很多人在spring cloud中FeignClientFactoryB
千家信息网最后更新 2024年12月03日spring cloud中FeignClientFactoryBean的原理和作用是什么

这篇文章主要介绍"spring cloud中FeignClientFactoryBean的原理和作用是什么",在日常操作中,相信很多人在spring cloud中FeignClientFactoryBean的原理和作用是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"spring cloud中FeignClientFactoryBean的原理和作用是什么"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

本文主要研究一下spring cloud的FeignClientFactoryBean

FeignClientFactoryBean

spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/FeignClientFactoryBean.java

class FeignClientFactoryBean                implements FactoryBean, InitializingBean, ApplicationContextAware {        /***********************************         * WARNING! Nothing in this class should be @Autowired. It causes NPEs because of some         * lifecycle race condition.         ***********************************/        private Class type;        private String name;        private String url;        private String contextId;        private String path;        private boolean decode404;        private ApplicationContext applicationContext;        private Class fallback = void.class;        private Class fallbackFactory = void.class;        @Override        public void afterPropertiesSet() throws Exception {                Assert.hasText(this.contextId, "Context id must be set");                Assert.hasText(this.name, "Name must be set");        }        @Override        public Object getObject() throws Exception {                return getTarget();        }        @Override        public Class getObjectType() {                return this.type;        }        @Override        public boolean isSingleton() {                return true;        }        @Override        public void setApplicationContext(ApplicationContext context) throws BeansException {                this.applicationContext = context;        }         T getTarget() {                FeignContext context = this.applicationContext.getBean(FeignContext.class);                Feign.Builder builder = 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,                                        new HardCodedTarget<>(this.type, this.name, this.url));                }                if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {                        this.url = "http://" + this.url;                }                String url = this.url + cleanPath();                Client client = getOptional(context, Client.class);                if (client != null) {                        if (client instanceof LoadBalancerFeignClient) {                                // not load balancing because we have a url,                                // but ribbon is on the classpath, so unwrap                                client = ((LoadBalancerFeignClient) client).getDelegate();                        }                        builder.client(client);                }                Targeter targeter = get(context, Targeter.class);                return (T) targeter.target(this, builder, context,                                new HardCodedTarget<>(this.type, this.name, url));        }        private String cleanPath() {                String path = this.path.trim();                if (StringUtils.hasLength(path)) {                        if (!path.startsWith("/")) {                                path = "/" + path;                        }                        if (path.endsWith("/")) {                                path = path.substring(0, path.length() - 1);                        }                }                return path;        }        //......}
  • FeignClientFactoryBean实现了FactoryBean的getObject、getObjectType、isSingleton方法;实现了InitializingBean的afterPropertiesSet方法;实现了ApplicationContextAware的setApplicationContext方法

  • getObject调用的是getTarget方法,它从applicationContext取出FeignContext,然后构造Feign.Builder并设置了logger、encoder、decoder、contract,之后通过configureFeign根据FeignClientProperties来进一步配置Feign.Builder的retryer、errorDecoder、request.Options、requestInterceptors、queryMapEncoder、decode404

  • 初步配置完Feign.Builder之后再判断是否需要loadBalance,如果需要则通过loadBalance方法来设置,不需要则在Client是LoadBalancerFeignClient的时候进行unwrap

FeignClientProperties

spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/FeignClientProperties.java

@ConfigurationProperties("feign.client")public class FeignClientProperties {        private boolean defaultToProperties = true;        private String defaultConfig = "default";        private Map config = new HashMap<>();        public boolean isDefaultToProperties() {                return this.defaultToProperties;        }        public void setDefaultToProperties(boolean defaultToProperties) {                this.defaultToProperties = defaultToProperties;        }        public String getDefaultConfig() {                return this.defaultConfig;        }        public void setDefaultConfig(String defaultConfig) {                this.defaultConfig = defaultConfig;        }        public Map getConfig() {                return this.config;        }        public void setConfig(Map config) {                this.config = config;        }        @Override        public boolean equals(Object o) {                if (this == o) {                        return true;                }                if (o == null || getClass() != o.getClass()) {                        return false;                }                FeignClientProperties that = (FeignClientProperties) o;                return this.defaultToProperties == that.defaultToProperties                                && Objects.equals(this.defaultConfig, that.defaultConfig)                                && Objects.equals(this.config, that.config);        }        @Override        public int hashCode() {                return Objects.hash(this.defaultToProperties, this.defaultConfig, this.config);        }        /**         * Feign client configuration.         */        public static class FeignClientConfiguration {                private Logger.Level loggerLevel;                private Integer connectTimeout;                private Integer readTimeout;                private Class retryer;                private Class errorDecoder;                private List> requestInterceptors;                private Boolean decode404;                private Class decoder;                private Class encoder;                private Class contract;                public Logger.Level getLoggerLevel() {                        return this.loggerLevel;                }                public void setLoggerLevel(Logger.Level loggerLevel) {                        this.loggerLevel = loggerLevel;                }                public Integer getConnectTimeout() {                        return this.connectTimeout;                }                public void setConnectTimeout(Integer connectTimeout) {                        this.connectTimeout = connectTimeout;                }                public Integer getReadTimeout() {                        return this.readTimeout;                }                public void setReadTimeout(Integer readTimeout) {                        this.readTimeout = readTimeout;                }                public Class getRetryer() {                        return this.retryer;                }                public void setRetryer(Class retryer) {                        this.retryer = retryer;                }                public Class getErrorDecoder() {                        return this.errorDecoder;                }                public void setErrorDecoder(Class errorDecoder) {                        this.errorDecoder = errorDecoder;                }                public List> getRequestInterceptors() {                        return this.requestInterceptors;                }                public void setRequestInterceptors(                                List> requestInterceptors) {                        this.requestInterceptors = requestInterceptors;                }                public Boolean getDecode404() {                        return this.decode404;                }                public void setDecode404(Boolean decode404) {                        this.decode404 = decode404;                }                public Class getDecoder() {                        return this.decoder;                }                public void setDecoder(Class decoder) {                        this.decoder = decoder;                }                public Class getEncoder() {                        return this.encoder;                }                public void setEncoder(Class encoder) {                        this.encoder = encoder;                }                public Class getContract() {                        return this.contract;                }                public void setContract(Class contract) {                        this.contract = contract;                }                @Override                public boolean equals(Object o) {                        if (this == o) {                                return true;                        }                        if (o == null || getClass() != o.getClass()) {                                return false;                        }                        FeignClientConfiguration that = (FeignClientConfiguration) o;                        return this.loggerLevel == that.loggerLevel                                        && Objects.equals(this.connectTimeout, that.connectTimeout)                                        && Objects.equals(this.readTimeout, that.readTimeout)                                        && Objects.equals(this.retryer, that.retryer)                                        && Objects.equals(this.errorDecoder, that.errorDecoder)                                        && Objects.equals(this.requestInterceptors, that.requestInterceptors)                                        && Objects.equals(this.decode404, that.decode404)                                        && Objects.equals(this.encoder, that.encoder)                                        && Objects.equals(this.decoder, that.decoder)                                        && Objects.equals(this.contract, that.contract);                }                @Override                public int hashCode() {                        return Objects.hash(this.loggerLevel, this.connectTimeout, this.readTimeout,                                        this.retryer, this.errorDecoder, this.requestInterceptors,                                        this.decode404, this.encoder, this.decoder, this.contract);                }        }}
  • FeignClientProperties有个Map结构的config,key是feign client的名称,默认是default,value是FeignClientConfiguration;FeignClientConfiguration包含了loggerLevel、connectTimeout、readTimeout、retryer、errorDecoder、requestInterceptors、decode404、decoder、encoder、contract属性

小结

  • FeignClientFactoryBean实现了FactoryBean的getObject、getObjectType、isSingleton方法;实现了InitializingBean的afterPropertiesSet方法;实现了ApplicationContextAware的setApplicationContext方法

  • getObject调用的是getTarget方法,它从applicationContext取出FeignContext,然后构造Feign.Builder并设置了logger、encoder、decoder、contract,之后通过configureFeign根据FeignClientProperties来进一步配置Feign.Builder的retryer、errorDecoder、request.Options、requestInterceptors、queryMapEncoder、decode404

  • 初步配置完Feign.Builder之后再判断是否需要loadBalance,如果需要则通过loadBalance方法来设置,不需要则在Client是LoadBalancerFeignClient的时候进行unwrap

到此,关于"spring cloud中FeignClientFactoryBean的原理和作用是什么"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0