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

相关推荐
轻语呢喃28 分钟前
JavaScript :字符串模板——优雅编程的基石
前端·javascript·后端
MikeWe34 分钟前
Paddle张量操作全解析:从基础创建到高级应用
后端
岫珩42 分钟前
Ubuntu系统关闭防火墙的正确方式
后端
心之语歌1 小时前
Java高效压缩技巧:ZipOutputStream详解
java·后端
不死的精灵2 小时前
【Java21】在spring boot中使用ScopedValue
java·spring boot·后端
M1A12 小时前
TCP/IP协议精解:IP协议——互联网世界的邮政编码系统
后端·网络协议·tcp/ip
逸风尊者2 小时前
开发易掌握的知识:GeoHash查找附近空闲车辆
java·后端
程序猿阿越4 小时前
Kafka源码(一)Controller选举与创建Topic
java·后端·源码
程序员爱钓鱼4 小时前
Go语言项目工程化 — 常见开发工具与 CI/CD 支持
开发语言·后端·golang·gin
Jiude4 小时前
MinIO 社区版被故意阉割,Web管理功能全面移除。我来试试国产RustFS
后端·docker·架构