天天看點

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

在feign整合sentinel時遇到了一個問題,折騰了一天,發現是@EnableFeignClients掃包的問題

具體錯誤:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.yushanma.service.ProductService': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
	at com.yushanma.TestApplication.main(TestApplication.java:21) ~[classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.yushanma.service.ProductService': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1884) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1268) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:267) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1605) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1562) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1343) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.3.jar:5.3.3]
	... 20 common frames omitted
Caused by: java.lang.NullPointerException: null
	at com.alibaba.cloud.sentinel.feign.SentinelFeign$Builder$1.create(SentinelFeign.java:92) ~[spring-cloud-starter-alibaba-sentinel-2020.0.RC1.jar:2020.0.RC1]
	at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:64) ~[feign-core-10.10.1.jar:na]
	at feign.Feign$Builder.target(Feign.java:269) ~[feign-core-10.10.1.jar:na]
	at org.springframework.cloud.openfeign.DefaultTargeter.target(DefaultTargeter.java:30) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:306) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:335) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:315) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:169) ~[spring-beans-5.3.3.jar:5.3.3]
	... 31 common frames omitted


Process finished with exit code 1
           

雖然用了@EnableFeignClients注解,但是在微服務多子產品項目中也掃不到@FeignClient注解的類,這個類沒有生成執行個體,在controller中@Autowire就沒有辦法注入依賴,最後報不滿足依賴的錯誤。

解決方法:指定掃描@FeignClient所在的包路徑

package com.yushanma;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication//(scanBasePackages = {"com.yushanma.service","com.yushanma.controller"})
//@EnableDiscoveryClient
@EnableFeignClients(basePackages="com.yushanma.fallback")
//@EnableFeignClients
//@SpringCloudApplication
@MapperScan("com.pojo.mapper")
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class);
    }
}
           
springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

關閉商品微服務後,訂單微服務進入容錯邏輯

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

完整代碼

package com.yushanma.service;

//Product product =
//        restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);


import com.pojo.model.Product;
import com.yushanma.config.FeignConfiguration;
import com.yushanma.fallback.EchoServiceFallback;
import com.yushanma.fallback.EchoServiceFallbackFactory;
import com.yushanma.fallback.ProductServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(
        name = "service-product",
//        fallback = ProductServiceFallback.class
//        fallbackFactory = ProductServiceFallBackFactory.class
        fallbackFactory = EchoServiceFallbackFactory.class,
        primary = true
//        fallback = EchoServiceFallback.class,
//        configuration = FeignConfiguration.class
)

public interface ProductService {

    //@[email protected] 就是一個完整的請求路徑 http://service-product/product/{pid}
    @RequestMapping(method = RequestMethod.GET, value = "/product/{pid}")
    Product findByPid(@PathVariable("pid") Integer pid);
}

           
package com.yushanma.fallback;

import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

@Component
public class EchoServiceFallbackFactory implements FallbackFactory<EchoServiceFallback> {

    @Override
    public EchoServiceFallback create(Throwable throwable) {
        return new EchoServiceFallback(throwable);
    }

}
           
package com.yushanma.fallback;

import com.pojo.model.Product;
import com.yushanma.service.ProductService;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class EchoServiceFallback implements ProductService {
    private Throwable throwable;

    EchoServiceFallback(Throwable throwable) {
        this.throwable = throwable;
    }

    @Override
    public Product findByPid(Integer pid) {
        Product product = new Product();
        product.setPid(-1);
        product.setPname("product-service調用出錯,進入容錯邏輯");
//        log.info("{}",throwable.getMessage());
        return product;
    }
}
           
package com.yushanma.controller;

import com.alibaba.fastjson.JSON;
import com.pojo.model.Order;
import com.pojo.model.Product;
import com.yushanma.service.OrderService;
import com.yushanma.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class ProductController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductService productService;

    //  基于Ribbon實作負載均衡
    @RequestMapping("order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info("查詢商品{}", pid);
        Product product = productService.findByPid(pid);
        //容錯處理
        if (product.getPid() == -1) {
            Order order = new Order();
            order.setPname("下單失敗");
            return order;

        }
        log.info("查詢到的商品資訊為{}", JSON.toJSONString(product));
        Order order = new Order();
        order.setUid(1);
        order.setUsername("yushanma");
        order.setPid(pid);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
//        orderService.createOrder(order);
        log.info("建立新的訂單{}", JSON.toJSONString(order));
        return order;
    }
}
           

但是出現後續問題:無論商品微服務是否開啟,訂單微服務一直進入容錯邏輯

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

發現是(basePackages="com.yushanma.fallback")的問題,應指定為"com.yushanma.service",但還是報空指針錯誤。最終考慮更換父工程版本:

<!--    父工程-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>
    <!--版本依賴的鎖定-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>
           

去掉feign的版本指定:

<!--fegin元件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- Feign Client for loadBalancing -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
           

不需再指定掃包:

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

開啟兩個服務後:請求下單成功

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

關閉商品微服務後下單:進入容錯邏輯

springcloud-alibaba feign整合sentinel 報不滿足依賴錯誤

至此,feign整合sentinel完成。

參考:

https://www.cnblogs.com/keeya/p/14476548.html

https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign-overriding-defaults

https://segmentfault.com/a/1190000018914017

https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example

繼續閱讀