Spring注解:@Component、@Repository、@Service——有何区别?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么Spring中三个注解做同一件事?

\n\n

每个刚开始使用Spring的人,迟早都会问这样一个问题:“为什么需要三个不同的注解——@Component、@Repository和@Service——如果它们都只是在上下文中注册一个Bean?”

\n\n

这个问题非常流行,在Stack Overflow上已经积累了数千次浏览和几十个回答。这并非偶然。乍一看,这些注解确实做着同样的事情。但正如常言所说,魔鬼藏在细节中。

\n\n

在本文中,我们不仅会列出区别。我们还将剖析Spring的设计哲学,深入容器内部,并展示正确使用注解如何能拯救你的项目,避免隐藏的Bug。让我们开始吧!

\n\n

快速入门:什么是原型注解?

\n\n

这三个注解都属于所谓的原型注解(stereotype annotations)。它们告诉Spring,该类是一个受管理的组件(Bean),并且应该在类路径扫描期间被自动发现。

\n\n

基础注解是@Component。它是基石。@Repository、@Service和@Controller是@Component的特化形式,它们添加了额外的语义和行为。

\n\n
@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@Component // 这是关键点!\npublic @interface Service {\n    // ...\n}
\n\n

如你所见,@Service本身被@Component注解。这意味着Spring会像处理普通@Component一样处理它。但为什么还要把事情搞复杂呢?

\n\n

@Component——万能士兵

\n\n

@Component是最通用的注解。当你的类不属于任何更具体的类别时,请使用它。

\n\n

典型示例:

\n
    \n
  • 辅助工具类
  • \n
  • 配置对象(不要与@Configuration混淆)
  • \n
  • 任何需要成为Bean,但不是服务、仓库或控制器的类
  • \n
\n\n
import org.springframework.stereotype.Component;\n\n@Component\npublic class EmailValidator {\n\n    public boolean isValid(String email) {\n        return email != null && email.contains("@");\n    }\n}
\n\n

请注意:EmailValidator不执行业务逻辑(它不是@Service),也不与数据库交互(它不是@Repository)。因此,@Component是理想的选择。

\n\n

@Repository——数据守护者

\n\n

@Repository是第一个添加了实际功能的特化注解。除了注册Bean之外,它还执行两个重要任务:

\n\n
    \n
  1. 拦截数据访问异常。Spring会自动将DAO(数据访问对象)的异常包装成DataAccessException——Spring的异常层次结构。
  2. \n
  3. 提高代码可读性。任何开发者看到@Repository,都会立刻明白:“啊,这里是在与数据库交互”。
  4. \n
\n\n
import org.springframework.stereotype.Repository;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n@Repository\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    User findByEmail(String email);\n}
\n\n

重要提示:如果你使用Spring Data JPA并继承自JpaRepository,Spring会自动创建代理Bean。显式添加@Repository注解并非必需,但建议使用以明确其用途。

\n\n

@Repository的主要“亮点”是AOP拦截器(PersistenceExceptionTranslationPostProcessor)

博客

书籍推荐