@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接口上是无效的。

相关推荐
why1515 小时前
腾讯(QQ浏览器)后端开发
开发语言·后端·golang
浪裡遊5 小时前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
声声codeGrandMaster5 小时前
django之优化分页功能(利用参数共存及封装来实现)
数据库·后端·python·django
呼Lu噜5 小时前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
bing_1586 小时前
为什么选择 Spring Boot? 它是如何简化单个微服务的创建、配置和部署的?
spring boot·后端·微服务
学c真好玩6 小时前
Django创建的应用目录详细解释以及如何操作数据库自动创建表
后端·python·django
Asthenia04126 小时前
GenericObjectPool——重用你的对象
后端
Piper蛋窝6 小时前
Go 1.18 相比 Go 1.17 有哪些值得注意的改动?
后端
excel6 小时前
招幕技术人员
前端·javascript·后端
盖世英雄酱581366 小时前
什么是MCP
后端·程序员