1. 程式人生 > >No fallback instance of type class found for feign client user-service(轉)

No fallback instance of type class found for feign client user-service(轉)

1、錯誤日誌

在 feign 開啟熔斷,配置 fallback 類,實現當前介面的實現類時,報錯資訊如下:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
ERROR 7204 --- [ main] o.s.boot.SpringApplication  : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: 
  Error creating bean with name
'consumerController':
Unsatisfied dependency expressed through field 'mUserClient';
nested exception is org.springframework.beans.factory.BeanCreationException:
  Error creating bean with name 'club.sscai.consumer.client.UserClient':
FactoryBean threw exception on object creation;
nested exception is
java.lang.IllegalStateException:
  No fallback instance of type class club.sscai.consumer.client.UserClientImpl found for feign client user-service

 

2、通常配置

1、開啟 hystrix(預設是關閉的):feign.hystrix.enabled=true

2、Fallback 介面實現類需要註解 @Component

如果到此處還沒有解決的話?請往下看。

 

3、轉載解決方案

跟蹤程式碼發現 是因為對FeignClient 這個介面做了AOP切面。

@Pointcut("execution(* com.xx.xx.service.IR*.*(..))")
public void remoteCall() {
}

Trace日誌看到這麼一行:

[DEBUG] [17:50:22.410][JdkDynamicAopProxy][117]:
Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [[email protected]]

然後考慮是不是因為Spring AOP動態代理預設為 JDK動態代理。

切面還是要切的,Fallback也不能放棄。因為呼叫的是介面,無論如何都要被切。

換成cglib後,問題成功解決。


 

原理
SpringAOP 的動態代理有兩種實現,JDK動態代理,和Cglib。
Spring預設使用 JDK動態代理。
當類至少實現了一個介面時,使用JDK動態代理。上文的Feign的Fallback類正好是這樣。
至於究竟為什麼cglib可以成功,就不去深究了,方案就兩個,非此即彼。
至於為什麼 找不到 fallback instance?

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<String>();

    // Check all bean definitions.
    for (String beanName : this.beanDefinitionNames) {
        // Only consider bean as eligible if the bean name
        // is not defined as alias for some other bean.
        if (!isAlias(beanName)) {
            try {
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // Only check bean definition if it is complete.
                if (!mbd.isAbstract() && (allowEagerInit ||
                   ((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
                   !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                    // In case of FactoryBean, match object created by FactoryBean.
                    boolean isFactoryBean = isFactoryBean(beanName, mbd);
                    boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
                    (includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);

......

問題出現在isTypeMatch

這裡isTypeMatch 返回了false,因為騙不過JVM型別檢查。當使用cglib則是匹配的。

 

原文地址:https://www.jianshu.com/p/c8210d878e96