The dependency version assumes every generic return type is a Class. That
* is false for declarations such as {@code Map}, whose runtime
* type is {@link ParameterizedType}; the failed cast used to hide the original
* downstream exception behind an AssertionError.
*/
public class DefaultFeignFallback implements MethodInterceptor {
private static final Logger log = LoggerFactory.getLogger(DefaultFeignFallback.class);
private final Class targetType;
private final String targetName;
private final Throwable cause;
public DefaultFeignFallback(Class targetType, String targetName, Throwable cause) {
this.targetType = targetType;
this.targetName = targetName;
this.cause = cause;
}
@Override
public Object intercept(Object object, Method method, Object[] arguments, MethodProxy methodProxy) {
log.error("FunFeignFallback:[{}.{}] serviceId:[{}] message:[{}]",
targetType.getName(), method.getName(), targetName, cause == null ? null : cause.getMessage());
Type declaredReturnType = method.getGenericReturnType();
Class> returnType = rawType(declaredReturnType);
Object data = defaultValue(returnType);
// Only methods that explicitly declare ResponseData may receive a
// ResponseData fallback. Returning it from Map/List methods causes a
// second ClassCastException in the Feign proxy.
if (ResponseData.class.equals(returnType)) {
Type dataType = firstTypeArgument(declaredReturnType);
return ResponseData.builder()
.code(ErrorCodeConstants.FAIL.getValue())
.msg("系统降级,请稍后再试!")
.data(defaultValue(rawType(dataType)))
.build();
}
return data;
}
private Type firstTypeArgument(Type type) {
if (type instanceof ParameterizedType) {
Type[] arguments = ((ParameterizedType) type).getActualTypeArguments();
if (arguments.length > 0) return arguments[0];
}
return null;
}
private Class> rawType(Type type) {
if (type instanceof Class>) return (Class>) type;
if (type instanceof ParameterizedType) return rawType(((ParameterizedType) type).getRawType());
return Object.class;
}
private Object defaultValue(Class> type) {
if (List.class.isAssignableFrom(type)) return new ArrayList