@Component、@Service、@Repository、@Controller的源码有区别吗
所以从源码上来讲,@Component、@Service、@Repository、@Controller没有任何区别对吗?
非常接近了!你说的基本对,但还有一点点关键的差异,主要体现在:
从源码实现上看,它们本质上都是@Component的"派生注解",所以它们最终都会被Spring扫描成 Bean,没有区别。
但——在一些具体功能实现上,Spring对这些注解确实会做一些"额外处理",这就引出了它们的区别。
✅ 首先看它们的源码结构(全都继承自@Component)
来看每个注解的源码:
@Component
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Component { String value() default ""; }
@Service
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { String value() default ""; }
@Repository
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { String value() default ""; }
@Controller
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String value() default ""; }
✅ 所以从注解继承角度,它们确实完全等价,都被认为是Spring的组件,都会被@ComponentScan扫描注册为Bean。
❗ 但它们的"行为"真的完全一样吗?并不完全一样!
下面列举Spring对不同注解做的"特别处理":
🧠 1. @Repository有异常翻译机制
当你用@Repository标注DAO类时,Spring会做一件额外的事:
捕捉原始数据库异常,并将其转为Spring自己的异常类型(比如 DataAccessException)。
这叫做:
Repository exception translation(数据访问异常翻译)
源码位置:
org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
这在使用MyBatis/JPA时特别有用,不然很多数据库异常你得自己try-catch。
🧠 2. @Controller会被Spring MVC专门处理
- 标识这个类是Web请求处理器。
- @RequestMapping、@GetMapping等注解的识别,是通过识别@Controller或@RestController的类来实现的。
它和普通 Bean不一样,它还被交给了 Spring MVC DispatcherServlet 专门处理请求分发。
🧠 3. @Service没有特别的行为,但它是AOP建议的目标
虽然@Service本身没有额外功能,但它通常被用于AOP的增强目标(比如事务处理、日志、监控等)。
所以如果你用@Service标注类,写个切面@Around("execution(* com.xxx.service..*(..))")更好匹配。
✅ 结论总结一下:
注解 | 是Bean吗? | 有额外行为? | 使用目的 |
@Component | ✅ | ❌ | 通用组件注册 |
@Service | ✅ | 🚫(无额外行为) | 语义上表示"业务服务层" |
@Repository | ✅ | ✅ 异常转换机制 | DAO层组件、数据库操作类 |
@Controller | ✅ | ✅ Spring MVC 控制器 | 控制请求、返回视图或JSON响应 |
所以你说得没错:如果只是从Bean注册的角度看,它们没有本质区别。
但在Spring的运行时逻辑里,确实有一层"语义驱动的特殊处理",而这就是Spring精妙的地方:不仅统一处理Bean,还按职责分工做细节增强。