mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 12:39:05 +08:00
fix(feign): 修复首次并发请求转换器竞态
This commit is contained in:
1 parent
d3afca673e
commit
2ab4d66f28
4 files changed
+112
-1
No files matched your search
@@ -18,6 +18,11 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<!-- FeignHttpMessageConverters 构造参数 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-http-converter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-jackson2</artifactId>
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.common.feign;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||
import org.springframework.cloud.openfeign.support.FeignHttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* PIGX Feign 客户端子上下文配置。
|
||||
* <p>
|
||||
* 不加 @Configuration:该类仅通过 defaultConfiguration 注册到 Feign 子上下文,
|
||||
* 避免被 pigx-boot 等主上下文组件扫描误引入。
|
||||
*
|
||||
* @author lengleng
|
||||
*/
|
||||
public class PigxFeignClientConfiguration {
|
||||
|
||||
/**
|
||||
* 构建并预热 Feign 消息转换器。
|
||||
* @param customizers Spring Boot 客户端转换器定制器
|
||||
* @param cloudCustomizers Spring Cloud 转换器定制器
|
||||
* @return 已完成初始化的 FeignHttpMessageConverters
|
||||
*/
|
||||
@Bean
|
||||
public FeignHttpMessageConverters pigxFeignHttpMessageConverters(
|
||||
ObjectProvider<ClientHttpMessageConvertersCustomizer> customizers,
|
||||
ObjectProvider<HttpMessageConverterCustomizer> cloudCustomizers) {
|
||||
FeignHttpMessageConverters converters = new FeignHttpMessageConverters(customizers, cloudCustomizers);
|
||||
// OpenFeign 5.0.2 在首次调用 getConverters() 时会先发布空列表再填充内容。
|
||||
// Feign 子上下文创建 Bean 时预热,避免并发首请求读到尚未初始化完成的空列表。
|
||||
converters.getConverters();
|
||||
return converters;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-1
@@ -17,6 +17,7 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.feign.annotation;
|
||||
|
||||
import com.pig4cloud.pigx.common.feign.PigxFeignClientConfiguration;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
@@ -68,11 +69,15 @@ public @interface EnablePigxFeignClients {
|
||||
* A custom <code>@Configuration</code> for all feign clients. Can contain override
|
||||
* <code>@Bean</code> definition for the pieces that make up the client, for instance
|
||||
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
|
||||
* <p>
|
||||
* 注意:显式指定该属性会整体替换默认值,即丢失
|
||||
* {@link PigxFeignClientConfiguration} 的消息转换器预热能力;如需自定义,
|
||||
* 请把 {@code PigxFeignClientConfiguration.class} 一并加入数组。
|
||||
*
|
||||
* @see FeignClientsConfiguration for the defaults
|
||||
*/
|
||||
@AliasFor(annotation = EnableFeignClients.class)
|
||||
Class<?>[] defaultConfiguration() default {};
|
||||
Class<?>[] defaultConfiguration() default { PigxFeignClientConfiguration.class };
|
||||
|
||||
/**
|
||||
* List of classes annotated with @FeignClient. If not empty, disables classpath
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.pig4cloud.pigx.common.feign;
|
||||
|
||||
import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.support.FeignHttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PigxFeignClientConfigurationTests {
|
||||
|
||||
@EnablePigxFeignClients
|
||||
private static class TestApplication {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInitializeConvertersBeforePublishingBean() {
|
||||
AtomicBoolean initialized = new AtomicBoolean();
|
||||
StaticListableBeanFactory clientCustomizerFactory = new StaticListableBeanFactory();
|
||||
clientCustomizerFactory.addBean("initializationProbe",
|
||||
(ClientHttpMessageConvertersCustomizer) builder -> initialized.set(true));
|
||||
StaticListableBeanFactory cloudCustomizerFactory = new StaticListableBeanFactory();
|
||||
|
||||
FeignHttpMessageConverters converters = new PigxFeignClientConfiguration().pigxFeignHttpMessageConverters(
|
||||
clientCustomizerFactory.getBeanProvider(ClientHttpMessageConvertersCustomizer.class),
|
||||
cloudCustomizerFactory.getBeanProvider(HttpMessageConverterCustomizer.class));
|
||||
|
||||
assertThat(initialized).isTrue();
|
||||
assertThat(converters.getConverters()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRegisterWarmupConfigurationForAllFeignClients() {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(TestApplication.class,
|
||||
EnableFeignClients.class);
|
||||
|
||||
assertThat(attributes).isNotNull();
|
||||
assertThat(attributes.getClassArray("defaultConfiguration")).contains(PigxFeignClientConfiguration.class);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user