From 9d356d4c1e6707303522a3ce02d5c80960006241 Mon Sep 17 00:00:00 2001 From: min1854 <102911352+min1854@users.noreply.github.com> Date: Mon, 20 Feb 2023 16:04:40 +0800 Subject: [PATCH] fallback support factoryBean 2021.x branch (#3162) feign fallback support factoryBean --- .../cloud/sentinel/feign/SentinelFeign.java | 12 +++ ...ntinelFallbackSupportFactoryBeanTests.java | 102 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFallbackSupportFactoryBeanTests.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java index b9d36ebf9..d867f9a59 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java @@ -27,6 +27,7 @@ import feign.InvocationHandlerFactory; import feign.Target; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FeignClientFactoryBean; @@ -41,6 +42,7 @@ import org.springframework.util.StringUtils; * {@link Feign.Builder}. * * @author Jim + * @author 黄学敏(huangxuemin) */ public final class SentinelFeign { @@ -126,6 +128,16 @@ public final class SentinelFeign { "No %s instance of type %s found for feign client %s", type, fallbackType, name)); } + // when fallback is a FactoryBean, should determine the type of instance + if (fallbackInstance instanceof FactoryBean) { + try { + fallbackInstance = ((FactoryBean) fallbackInstance).getObject(); + } + catch (Exception e) { + throw new IllegalStateException(type + " create fail", e); + } + fallbackType = fallbackInstance.getClass(); + } if (!targetType.isAssignableFrom(fallbackType)) { throw new IllegalStateException(String.format( diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFallbackSupportFactoryBeanTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFallbackSupportFactoryBeanTests.java new file mode 100644 index 000000000..ae578416e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFallbackSupportFactoryBeanTests.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013-2023 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 com.alibaba.cloud.sentinel; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author 黄学敏(huangxuemin) + */ +public class SentinelFallbackSupportFactoryBeanTests { + + private static final String FACTORY_BEAN_FALLBACK_MESSAGE = "factoryBean fallback message"; + + private static final String ORIGINAL_FALLBACK_MESSAGE = "OriginalFeign fallback message"; + + private final ApplicationContextRunner runner = new ApplicationContextRunner() + .withBean(FactoryBeanFallbackFeignFallback.class) + .withBean(OriginalFeignFallback.class) + .withConfiguration(AutoConfigurations.of(TestConfiguration.class, FeignAutoConfiguration.class)) + .withPropertyValues("feign.sentinel.enabled=true"); + + @Test + public void shouldRunFallbackFromBeanOrFactoryBean() { + runner.run(ctx -> { + assertThat(ctx.getBean(OriginalFeign.class).get()).isEqualTo(ORIGINAL_FALLBACK_MESSAGE); + assertThat(ctx.getBean(FactoryBeanFallbackFeign.class).get()).isEqualTo(FACTORY_BEAN_FALLBACK_MESSAGE); + }); + } + + @Configuration(proxyBeanMethods = false) + @EnableFeignClients(clients = {OriginalFeign.class, FactoryBeanFallbackFeign.class }) + @EnableAutoConfiguration + public static class TestConfiguration { + + } + + @FeignClient(name = "original", url = "https://original", fallback = OriginalFeignFallback.class) + interface OriginalFeign { + + @GetMapping("/") + String get(); + + } + + @FeignClient(name = "factoryBean", url = "https://factoryBean", fallback = FactoryBeanFallbackFeignFallback.class) + interface FactoryBeanFallbackFeign { + + @GetMapping("/") + String get(); + + } + + private static class FactoryBeanFallbackFeignFallback implements FactoryBean { + + @Override + public FactoryBeanFallbackFeign getObject() { + return () -> FACTORY_BEAN_FALLBACK_MESSAGE; + } + + @Override + public Class getObjectType() { + return FactoryBeanFallbackFeign.class; + } + + } + + private static class OriginalFeignFallback implements OriginalFeign { + + @Override + public String get() { + return ORIGINAL_FALLBACK_MESSAGE; + } + + } + +}