diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/pom.xml
index 3b52c94c3..28604c272 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/pom.xml
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/pom.xml
@@ -77,13 +77,13 @@
org.springframework.cloud
- spring-cloud-starter-loadbalancer
+ spring-cloud-commons
true
org.springframework.cloud
- spring-cloud-commons
+ spring-cloud-starter-loadbalancer
true
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 bb8044748..953463ad6 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
@@ -25,16 +25,20 @@ import feign.Contract;
import feign.Feign;
import feign.InvocationHandlerFactory;
import feign.Target;
-//import feign.hystrix.FallbackFactory;
-//import feign.hystrix.HystrixFeign;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
+import static org.springframework.beans.factory.BeanFactory.FACTORY_BEAN_PREFIX;
+
/**
* {@link Feign.Builder} like {@link HystrixFeign.Builder}.
*
@@ -77,38 +81,43 @@ public final class SentinelFeign {
@Override
public InvocationHandler create(Target target,
Map dispatch) {
- // using reflect get fallback and fallbackFactory properties from
- // FeignClientFactoryBean because FeignClientFactoryBean is a package
- // level class, we can not use it in our package
-// Object feignClientFactoryBean = Builder.this.applicationContext
-// .getBean("&" + target.type().getName());
-//
-// Class fallback = (Class) getFieldValue(feignClientFactoryBean,
-// "fallback");
-// Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean,
-// "fallbackFactory");
-// String beanName = (String) getFieldValue(feignClientFactoryBean,
-// "contextId");
-// if (!StringUtils.hasText(beanName)) {
-// beanName = (String) getFieldValue(feignClientFactoryBean, "name");
-// }
-//
-// Object fallbackInstance;
-// FallbackFactory fallbackFactoryInstance;
-// // check fallback and fallbackFactory properties
-// if (void.class != fallback) {
-// fallbackInstance = getFromContext(beanName, "fallback", fallback,
-// target.type());
-// return new SentinelInvocationHandler(target, dispatch,
-// new FallbackFactory.Default(fallbackInstance));
-// }
-// if (void.class != fallbackFactory) {
-// fallbackFactoryInstance = (FallbackFactory) getFromContext(
-// beanName, "fallbackFactory", fallbackFactory,
-// FallbackFactory.class);
-// return new SentinelInvocationHandler(target, dispatch,
-// fallbackFactoryInstance);
-// }
+
+ GenericApplicationContext gctx = (GenericApplicationContext) Builder.this.applicationContext;
+ BeanDefinition def = gctx.getBeanDefinition(target.type().getName());
+
+ /**
+ * TODO
+ * 由于初始化顺序发生变更,这里为了避免循环依赖,只能通过 BeanDefinition 的方式获得 FeignClientFactoryBean
+ * 需要重点review
+ */
+// FeignClientFactoryBean feignClientFactoryBean = (FeignClientFactoryBean) Builder.this.applicationContext
+// .getBean(FACTORY_BEAN_PREFIX + target.type().getName());
+ FeignClientFactoryBean feignClientFactoryBean = (FeignClientFactoryBean) def.getAttribute("feignClientsRegistrarFactoryBean");
+
+ Class fallback = feignClientFactoryBean.getFallback();
+ Class fallbackFactory = feignClientFactoryBean.getFallbackFactory();
+ String beanName = feignClientFactoryBean.getContextId();
+
+ if (!StringUtils.hasText(beanName)) {
+ beanName = feignClientFactoryBean.getName();
+ }
+
+ Object fallbackInstance;
+ FallbackFactory fallbackFactoryInstance;
+ // check fallback and fallbackFactory properties
+ if (void.class != fallback) {
+ fallbackInstance = getFromContext(beanName, "fallback", fallback,
+ target.type());
+ return new SentinelInvocationHandler(target, dispatch,
+ new FallbackFactory.Default(fallbackInstance));
+ }
+ if (void.class != fallbackFactory) {
+ fallbackFactoryInstance = (FallbackFactory) getFromContext(
+ beanName, "fallbackFactory", fallbackFactory,
+ FallbackFactory.class);
+ return new SentinelInvocationHandler(target, dispatch,
+ fallbackFactoryInstance);
+ }
return new SentinelInvocationHandler(target, dispatch);
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java
index 85144c05f..18ff4e7e7 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java
@@ -23,6 +23,8 @@ import java.lang.reflect.Proxy;
import java.util.LinkedHashMap;
import java.util.Map;
+import org.springframework.cloud.openfeign.FallbackFactory;
+
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
@@ -47,8 +49,18 @@ public class SentinelInvocationHandler implements InvocationHandler {
private final Map dispatch;
+ private FallbackFactory fallbackFactory;
+
private Map fallbackMethodMap;
+ SentinelInvocationHandler(Target> target, Map dispatch,
+ FallbackFactory fallbackFactory) {
+ this.target = checkNotNull(target, "target");
+ this.dispatch = checkNotNull(dispatch, "dispatch");
+ this.fallbackFactory = fallbackFactory;
+ this.fallbackMethodMap = toFallbackMethod(dispatch);
+ }
+
SentinelInvocationHandler(Target> target, Map dispatch) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch");
@@ -100,8 +112,25 @@ public class SentinelInvocationHandler implements InvocationHandler {
if (!BlockException.isBlockException(ex)) {
Tracer.trace(ex);
}
- // throw exception if fallbackFactory is null
- throw ex;
+ if (fallbackFactory != null) {
+ try {
+ Object fallbackResult = fallbackMethodMap.get(method)
+ .invoke(fallbackFactory.create(ex), args);
+ return fallbackResult;
+ }
+ catch (IllegalAccessException e) {
+ // shouldn't happen as method is public due to being an
+ // interface
+ throw new AssertionError(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new AssertionError(e.getCause());
+ }
+ }
+ else {
+ // throw exception if fallbackFactory is null
+ throw ex;
+ }
}
finally {
if (entry != null) {