zoukankan      html  css  js  c++  java
  • 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 [com.xx.xx.service.HystrixClientFallback@32354b00]

    然后考虑是不是因为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

  • 相关阅读:
    Docker容器监控(十)--技术流ken
    Docker跨主机通信(九)--技术流ken
    Docker多主机管理(八)--技术流ken
    Docker公共&本地镜像仓库(七)--技术流ken
    Docker镜像构建的两种方式(六)--技术流ken
    Docker网络(五)--技术流ken
    tomcat使用详解(week4_day2)--技术流ken
    haproxy使用演示--技术流ken
    xshell连接虚拟机详解--技术流ken
    grafana使用详解--技术流ken
  • 原文地址:https://www.cnblogs.com/niceyoo/p/10051907.html
Copyright © 2011-2022 走看看