@Resouce引发的错误

还原现场

优化前的代码:

java 复制代码
// package cn.com.servermanager.controller;

@RestController
public class ProcessingController {

    @Autowired
    private ProcessingServiceImpl processingService;

    @PostMapping("/xxxx")
    public Result getProcessingServer() {
        return processingService.getProcessingServer();
    }
}
java 复制代码
// package cn.com.servermanager.service;

@Service
public class ProcessingServiceImpl {

    @Autowired
    private ProcessingFeignService processingFeignService;

    public Result getProcessingServer() {
        return processingFeignService.getProcessingServer();
    }
}
java 复制代码
// package cn.com.servermanager.feignclient;

@ConditionalOnClass({Feign.class, Hystrix.class})
@Service
@FeignClient(
    name = GlobalConstants.MANAGER,
    path = "/xxxx",
    fallbackFactory = ProcessingFallbackFactory.class,
    contextId = "Processing")
public interface ProcessingFeignService {

    @PostMapping("/")
    Result getProcessingServer();
}

优化前,ProcessingServiceImpl只是对ProcessingFeignService做了简单的包装。优化后,删掉ProcessingServiceImpl,ProcessingController使用@Resource直接注入ProcessingFeignService

java 复制代码
// package cn.com.servermanager.controller;

@RestController
public class ProcessingController {

    @Resource
    ProcessingFeignService processingFeignService;

    @PostMapping("/xxxx")
    public Result getProcessingServer() {
        return processingFeignService.getProcessingServer();
    }
}

代码优化后程序正常启动,但是调用接口时报错:

java 复制代码
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.com.servermanager.feignclient.ProcessingFeignService.getProcessingServer
	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.<init>(MybatisMapperMethod.java:51)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedInvoker$0(MybatisMapperProxy.java:111)
	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
	at com.baomidou.mybatisplus.core.toolkit.CollectionUtils.computeIfAbsent(CollectionUtils.java:117)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedInvoker(MybatisMapperProxy.java:98)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
	at com.sun.proxy.$Proxy216.getGeoProcessingServerResp(Unknown Source)
	at cn.com.servermanager.controller.ProcessingController.getProcessingServer(ProcessingController.java:37)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)

处理

一个feignClient接口为何报ibatis相关的错误,难道是ibatis做了她不该做的事情?查看入口类的注解,果然ProcessingFeignService在MapperScan的扫描范围内

java 复制代码
@EnableFeignClients(basePackages = {"cn.com.common.feignclient", "cn.com.servermanager.feignclient"})
@SpringBootApplication()
@MapperScan("cn.com.servermanager.*")
@ComponentScan({"cn.com.servermanager", "cn.com.common"})
@ServletComponentScan
public class ServerManagerApplication {
    public static void main(String[] args) {
        // 无关代码省略      
    }

}

抛开细节简单说,通过查看@MapperScan和@EnableFeignClients的源码知晓:

1,被MapperScan扫描的接口会以非限定名作为beanName装配到spring的容器中,即spring容器中存在名为ProcessingFeignService的bean

2,被EnableFeignClients扫描的接口会以全限定名作为beanName并以contextId+"FeignClient"作为Alias装配到spring容器中,即spring容器中存在名为cn.com.servermanager.feignclient.ProcessingFeignService的bean,它的别名是ProcessingFeignClient

因此优化后的代码才会报ibatis的错误,因为通过@Resource注入的bean是被mybatis实例化的。

此时,摆在我们面前的解决方案有多种:

java 复制代码
// 原始代码
@Resource 
ProcessingFeignService processingFeignService;

// 方案一:修改变量名
@Resource 
ProcessingFeignService processingService; 

// 方案二:指定bean名称
@Resource(name = "ProcessingFeignClient")
ProcessingFeignService processingFeignService;

// 方案三:改用@Autowired
@Autowired
ProcessingFeignService processingFeignService;

方案一能生效的原因:@Resouce默认按照名称匹配bean,如果没找到则会按照类型匹配。

方案二能生效的原因:ProcessingFeignService在spring容器中的bean别名是ProcessingFeignClient。

方案三能生效的原因:@Autowired默认按照类型匹配bean。

问题解决了,但是还有两个需要优化的地方:

1,@MapperScan扫描的包范围尽量做到精确,避免粒度大装配太多无意义的bean。

2,@Service注解使用在ProcessingFeignService接口上是无效的。

相关推荐
非凡ghost5 小时前
PixPin截图工具(支持截长图截动图) 中文绿色版
前端·javascript·后端
武子康5 小时前
大数据-133 ClickHouse 概念与基础|为什么快?列式 + 向量化 + MergeTree 对比
大数据·后端·nosql
脚踏实地的大梦想家6 小时前
【Go】P11 掌握 Go 语言函数(二):进阶玩转高阶函数、闭包与 Defer/Panic/Recover
开发语言·后端·golang
用户68545375977696 小时前
🔥 服务熔断降级:微服务的"保险丝"大作战!
后端
Tech有道6 小时前
拼多多「面试官问我:LRU 和 LFU 你选谁?」我:看场景啊哥!😂
后端
用户68545375977696 小时前
🎬 开场:RPC框架的前世今生
后端
王中阳Go背后的男人6 小时前
Docker磁盘满了?这样清理高效又安全
后端·docker
用户68545375977696 小时前
🎛️ 分布式配置中心:让配置管理不再是噩梦!
后端
CodeFans6 小时前
Spring 浅析
后端
李广坤6 小时前
Filter(过滤器)、Interceptor(拦截器) 和 AOP(面向切面编程)
后端