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

相关推荐
舒一笑1 小时前
为什么where=Version就是乐观锁了?
后端·mysql·程序员
GoGeekBaird1 小时前
关于垂类AI应用落地行业的方法论思考
后端·github·agent
小宁爱Python1 小时前
Django 基础入门:命令、结构与核心配置全解析
后端·python·django
你的人类朋友2 小时前
认识一下Bcrypt哈希算法
后端·安全·程序员
tangweiguo030519872 小时前
基于 Django 与 Bootstrap 构建的现代化设备管理平台
后端·django·bootstrap
IT果果日记2 小时前
详解DataX开发达梦数据库插件
大数据·数据库·后端
dazhong20122 小时前
Spring Boot 项目新增 Module 完整指南
java·spring boot·后端
bobz9653 小时前
Cilium + Kubevirt 与 Kube-OVN + Kubevirt 在公有云场景下的对比与选择
后端
David爱编程4 小时前
深度解析:synchronized 性能演进史,从 JDK1.6 到 JDK17
java·后端
脑子慢且灵4 小时前
【JavaWeb】一个简单的Web浏览服务程序
java·前端·后端·servlet·tomcat·web·javaee