springboot Config类@Import导入Config类中bean覆盖方法

spring-cloud-openfeign-core第三方包里面有FeignClientsConfiguration.class里面是包括了feign需要的bean,但里面已经定义了feignEncoder、feignDecoder,如果项目中想要定制feignEncoder、feignDecoder就会冲突报错No bean found of type interface feign.codec.Encoder for XXXapi,但项目中有自定义这两个bean。显然这种在Config类@Import另一个Config类,又重定义里里面的bean,即使另一个Config类有用到@ConditionalOnMissingBean也不行,只需要在冲突的bean上加 @Primary就能正常加载了,而且另一个Config类冲突的bean也不会加载到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Logger;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.optionals.OptionalDecoder;
import io.vavr.jackson.datatype.VavrModule;
import okhttp3.ConnectionPool;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;<br>import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 
import java.util.concurrent.TimeUnit;
@Import(FeignClientsConfiguration.class)
@Configuration
public class FeignClientConfig {
    @Bean
    public okhttp3.OkHttpClient okHttpClient(){
        return new okhttp3.OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60,TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool())
                .build();
    }
    @Bean
    public Logger.Level feignLoggerLevel(){
        return  Logger.Level.BASIC;
    }
 
    @Bean<br>    @Primary
    public Encoder feignEncoder() {
        return new SpringEncoder(feignHttpMessageConverter());
    }
 
    @Bean<br>    @Primary
    public Decoder feignDecoder() {
        return new OptionalDecoder(
            new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter())));
    }
 
    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // Either 序列化问题
        objectMapper.registerModule(new VavrModule());
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return () -> new HttpMessageConverters(jackson2HttpMessageConverter);
    }
 
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
 * Copyright 2013-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package org.springframework.cloud.openfeign;
 
import java.util.ArrayList;
import java.util.List;
 
import feign.Contract;
import feign.Feign;
import feign.Logger;
import feign.QueryMapEncoder;
import feign.Retryer;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.form.MultipartFormContentProcessor;
import feign.form.spring.SpringFormEncoder;
import feign.micrometer.MicrometerCapability;
import feign.optionals.OptionalDecoder;
import io.micrometer.core.instrument.MeterRegistry;
 
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.openfeign.clientconfig.FeignClientConfigurer;
import org.springframework.cloud.openfeign.support.AbstractFormWriter;
import org.springframework.cloud.openfeign.support.FeignEncoderProperties;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
import org.springframework.cloud.openfeign.support.PageableSpringQueryMapEncoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
 
import static feign.form.ContentType.MULTIPART;
 
/**
 * @author Dave Syer
 * @author Venil Noronha
 * @author Darren Foong
 * @author Jonatan Ivanov
 * @author Olga Maciaszek-Sharma
 * @author Hyeonmin Park
 * @author Yanming Zhou
 */
@Configuration(proxyBeanMethods = false)
public class FeignClientsConfiguration {
 
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;
 
    @Autowired(required = false)
    private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>();
 
    @Autowired(required = false)
    private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>();
 
    @Autowired(required = false)
    private Logger logger;
 
    @Autowired(required = false)
    private SpringDataWebProperties springDataWebProperties;
 
    @Autowired(required = false)
    private FeignClientProperties feignClientProperties;
 
    @Autowired(required = false)
    private FeignEncoderProperties encoderProperties;
 
    @Bean
    @ConditionalOnMissingBean
    public Decoder feignDecoder(ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters, customizers)));
    }
 
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
    public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
            ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        return springEncoder(formWriterProvider, encoderProperties, customizers);
    }
 
    @Bean
    @ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
    @ConditionalOnMissingBean
    public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider,
            ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        PageableSpringEncoder encoder = new PageableSpringEncoder(
                springEncoder(formWriterProvider, encoderProperties, customizers));
 
        if (springDataWebProperties != null) {
            encoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
            encoder.setSizeParameter(springDataWebProperties.getPageable().getSizeParameter());
            encoder.setSortParameter(springDataWebProperties.getSort().getSortParameter());
        }
        return encoder;
    }
 
    @Bean
    @ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
    @ConditionalOnMissingBean
    public QueryMapEncoder feignQueryMapEncoderPageable() {
        PageableSpringQueryMapEncoder queryMapEncoder = new PageableSpringQueryMapEncoder();
        if (springDataWebProperties != null) {
            queryMapEncoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
            queryMapEncoder.setSizeParameter(springDataWebProperties.getPageable().getSizeParameter());
            queryMapEncoder.setSortParameter(springDataWebProperties.getSort().getSortParameter());
        }
        return queryMapEncoder;
    }
 
    @Bean
    @ConditionalOnMissingBean
    public Contract feignContract(ConversionService feignConversionService) {
        boolean decodeSlash = feignClientProperties == null || feignClientProperties.isDecodeSlash();
        return new SpringMvcContract(parameterProcessors, feignConversionService, decodeSlash);
    }
 
    @Bean
    public FormattingConversionService feignConversionService() {
        FormattingConversionService conversionService = new DefaultFormattingConversionService();
        for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) {
            feignFormatterRegistrar.registerFormatters(conversionService);
        }
        return conversionService;
    }
 
    @Bean
    @ConditionalOnMissingBean
    public Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }
 
    @Bean
    @ConditionalOnMissingBean(FeignLoggerFactory.class)
    public FeignLoggerFactory feignLoggerFactory() {
        return new DefaultFeignLoggerFactory(logger);
    }
 
    @Bean
    @ConditionalOnMissingBean(FeignClientConfigurer.class)
    public FeignClientConfigurer feignClientConfigurer() {
        return new FeignClientConfigurer() {
        };
    }
 
    private Encoder springEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
            FeignEncoderProperties encoderProperties, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        AbstractFormWriter formWriter = formWriterProvider.getIfAvailable();
 
        if (formWriter != null) {
            return new SpringEncoder(new SpringPojoFormEncoder(formWriter), messageConverters, encoderProperties,
                    customizers);
        }
        else {
            return new SpringEncoder(new SpringFormEncoder(), messageConverters, encoderProperties, customizers);
        }
    }
 
    private class SpringPojoFormEncoder extends SpringFormEncoder {
 
        SpringPojoFormEncoder(AbstractFormWriter formWriter) {
            super();
 
            MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
            processor.addFirstWriter(formWriter);
        }
 
    }
 
    @Configuration(proxyBeanMethods = false)
    @Conditional(FeignCircuitBreakerDisabledConditions.class)
    protected static class DefaultFeignBuilderConfiguration {
 
        @Bean
        @Scope("prototype")
        @ConditionalOnMissingBean
        public Feign.Builder feignBuilder(Retryer retryer) {
            return Feign.builder().retryer(retryer);
        }
 
    }
 
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(CircuitBreaker.class)
    @ConditionalOnProperty("feign.circuitbreaker.enabled")
    protected static class CircuitBreakerPresentFeignBuilderConfiguration {
 
        @Bean
        @Scope("prototype")
        @ConditionalOnMissingBean({ Feign.Builder.class, CircuitBreakerFactory.class })
        public Feign.Builder defaultFeignBuilder(Retryer retryer) {
            return Feign.builder().retryer(retryer);
        }
 
        @Bean
        @Scope("prototype")
        @ConditionalOnMissingBean
        @ConditionalOnBean(CircuitBreakerFactory.class)
        public Feign.Builder circuitBreakerFeignBuilder() {
            return FeignCircuitBreaker.builder();
        }
 
    }
 
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnBean(type = "io.micrometer.core.instrument.MeterRegistry")
    @ConditionalOnClass(name = "feign.micrometer.MicrometerCapability")
    @ConditionalOnProperty(name = "feign.metrics.enabled", matchIfMissing = true)
    @Conditional(FeignClientMetricsEnabledCondition.class)
    protected static class MetricsConfiguration {
 
        @Bean
        @ConditionalOnMissingBean
        public MicrometerCapability micrometerCapability(MeterRegistry meterRegistry) {
            return new MicrometerCapability(meterRegistry);
        }
 
    }
 
}

  

posted @   klm-kain  阅读(1035)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示