【MyBatis Plus】@Service标签应该放在ServiceImpl上(接口不可以实例化)

@Component****及其衍生注解(@Service/@Controller/@Repository)都不应该标注在接口上! @Service 注解要标注在 ServiceImpl(实现类)上而非 Service(接口)上,核心原因是 Spring 容器只能实例化 "具体类",无法实例化接口,且这是 Spring 依赖注入(DI)和面向接口编程的核心设计逻辑,我从「底层原理、实战意义、避坑点」三个维度讲透:

一、核心原理:Spring 容器的 "实例化规则"

  1. 接口无法被实例化 :Service 接口(如 UserService)只是方法定义,没有具体实现,JVM 本身就无法创建接口的对象;@Service 的本质是告诉 Spring:"把这个类实例化成 Bean,放到容器中"------ 接口连对象都创建不了,标注 @Service 毫无意义。

  2. 实现类是 "可实例化的具体类" :ServiceImpl(如 UserServiceImpl)是接口的具体实现,包含方法的完整逻辑,Spring 能通过反射创建它的实例,并将实例注册到 IoC 容器中。

    举个反例(错误写法):

    复制代码
    // ❌ 错误:接口加@Service,Spring无法实例化
    @Service
    public interface UserService {
        boolean login(String username, String password);
    }
    
    // ✅ 正确:实现类加@Service,Spring能创建实例
    public class UserServiceImpl implements UserService {
        @Override
        public boolean login(String username, String password) {
            // 业务逻辑
            return true;
        }
    }

    这种写法启动时会报错:No qualifying bean of type 'UserService' available(找不到 UserService 类型的 Bean)。

二、实战意义:面向接口编程 + 依赖注入

Spring 推荐 "面向接口编程",核心流程是:

  1. 定义接口 :UserService 定义业务方法(规范);

  2. 实现类加 @Service :UserServiceImpl 实现接口,加 @Service 让 Spring 实例化;

  3. 控制器注入接口 :

    java

    运行

    复制代码
    @RestController
    public class LoginController {
        // 注入接口(而非实现类),解耦
        @Autowired
        private UserService userService; 
    }
    • Spring 会自动找到 UserService 接口的实现类(UserServiceImpl),把容器中的实例注入到控制器;
    • 如果后续替换实现类(如 UserServiceV2Impl),只需修改实现类的 @Service,控制器代码无需改动(解耦核心)。

三、补充:为什么不能给接口加 @Service?

除了 "无法实例化",还有两个关键问题:

  1. 多实现类冲突 :如果一个接口有多个实现类(如 UserServiceImpl、AdminUserServiceImpl),若给接口加 @Service,Spring 无法判断该实例化哪个实现类,会报 NoUniqueBeanDefinitionException;
  2. 违背设计原则 :接口是 "契约",标注 @Service 这种 "容器相关注解" 会污染接口,接口应只关注业务方法定义,和容器解耦。
相关推荐
真上帝的左手13 小时前
30. 技术专题-‌应用框架组件-关系型数据库-MySQL-Mybatis
数据库·分布式·mysql·中间件·mybatis
雪芽蓝域zzs16 小时前
第 2 章:整合 MySQL + MyBatis,搭建数据库基础、实体类、Mapper、测试查询
数据库·mysql·mybatis
wljt1 天前
公司二-面试题
java·开发语言·mybatis
VimorphTech1 天前
文本已经改了,旧的音频生成结果还能回写吗?
java·数据库·mybatis
麻瓜code2 天前
双写一致性:为什么是“删缓存“,而不是“改缓存“
java·缓存·mybatis
郭小李2 天前
mybatis 动态 sql
java·sql·mybatis
知守观2 天前
技术考古:iBATIS 2.3.4 时代的持久层,是如何用 Map 玩转 307 个存储过程的?
java·后端·mybatis
captain3762 天前
MyBatis Plus(1)
java·服务器·mybatis
代码不停3 天前
MyBatis进阶
spring boot·mybatis
captain3763 天前
MyBatis(入门5)其他查询操作
java·数据库·spring boot·mybatis