Spring 中的 @ Component,@ Repository 和 @Service 批注有什么区别?

@Repository @Component@Repository@Service批注可以在 Spring 中互换使用吗,或者除了充当注解设备外,它们还提供任何特定功能吗?

换句话说,如果我有一个 Service 类,并且将注释从@Service更改为@Component ,它的行为是否仍将相同?

还是注释也会影响类的行为和功能?

答案

Spring 文档

在 Spring 2.0 和更高版本中, @Repository批注是满足存储库角色或构造型(也称为数据访问对象或 DAO)的任何类的标记。该标记的用途包括自动翻译例外。

Spring 2.5 引入了更多的@Component型注释: @Component@Service @Controller@Controller@Component是任何 Spring 托管组件的通用@Component型。 @Repository@Service @Controller@Controller@Component用于更具体的用例,例如分别在持久层,服务层和表示层中。

因此,您可以使用@Component注释组件类,但可以使用@Repository@Service @Controller@Controller注释组件类,这些类更适合于通过工具进行处理或与方面相关联。例如,这些构造型注释成为切入点的理想目标。

因此,如果在服务层使用@Component@Service之间进行选择,则@Service显然是更好的选择。同样,如上所述, @Repository已被支持作为持久层中自动异常转换的标记。

┌────────────┬─────────────────────────────────────────────────────┐
│ Annotation │ Meaning                                             │
├────────────┼─────────────────────────────────────────────────────┤
│ @Component │ generic stereotype for any Spring-managed component │
│ @Repository│ stereotype for persistence layer                    │
│ @Service   │ stereotype for service layer                        │
│ @Controller│ stereotype for presentation layer (spring-mvc)      │
└────────────┴─────────────────────────────────────────────────────┘

由于许多答案已经说明了这些批注的用途,因此我们将重点关注它们之间的一些细微差异。

首先相似

值得再次强调的第一点是, 关于 BeanDefinition 的扫描自动检测和依赖项注入,所有这些注释(即 @ Component,@ Service,@ Repository,@ Controller)都是相同的。 我们可以用一个代替另一个,并且仍然可以解决问题。


@ Component,@ Repository,@ Controller 和 @Service 之间的区别

@零件

这是一个通用的构造型注释,指示该类是弹簧组件。

@Component 有什么特别之处
<context:component-scan>仅扫描@Component ,通常不查找@Controller@Service @Controller@Repository 。扫描它们是因为它们本身带有@Component注释。

只需看看@Controller@Service @Controller@Repository注释定义:

@Component
public @interface Service {
    ….
}

@Component
public @interface Repository {
    ….
}

@Component
public @interface Controller {
    …
}

因此,说@Controller@Service @Controller@Repository@Component注释的特殊类型是没有错的。 <context:component-scan>拾取它们并将其以下类注册为 bean,就像它们使用@Component进行注释一样。

还扫描特殊类型的注释,因为它们本身使用@Component注释进行注释,这意味着它们也是@Component 。如果我们定义自己的自定义注释并使用@Component对其进行注释,则还将使用<context:component-scan>


@资料库

这表示该类定义了一个数据存储库。

@Repository 有什么特别之处?

除了指出这是基于Annotation 的 Configuration 之外@Repository的工作是捕获特定于平台的异常,并将它们作为 Spring 的统一未检查异常之一重新抛出。为此,我们提供了PersistenceExceptionTranslationPostProcessor ,我们需要将其添加到 Spring 的应用程序上下文中,如下所示:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

这个 bean 后处理器将顾问程序添加到任何用@Repository注释的 bean,以便捕获任何特定于平台的异常,然后将它们重新抛出为 Spring 的未经检查的数据访问异常之一。


@Controller

@Controller注释指示特定的类充当控制器的角色。 @Controller注释充当带注释的类的@Controller型,指示其作用。

@Controller 有什么特别之处?

即使它们看起来相同,我们也无法将其与@Service@Repository类的任何其他对象切换。调度程序扫描用@Controller注释的类,并在其中检测用@RequestMapping注释注释的方法。我们可以使用@RequestMapping上 / 只,其类注释与方法@Controller ,它不会与工作@Component@Service@Repository等..

注:如果一个类是通过任何替代方法通过已注册为一个 bean,像@Bean或通过@Component@Service等... 注释,然后@RequestMapping如果类也与注释可挑@RequestMapping注解。但这是另一种情况。


@服务

@Service bean 在存储库层中保存业务逻辑和调用方法。

@Service 有什么特别之处?

除了它用来指示它保持业务逻辑这一事实外,此注释中没有其他可注意到的东西。但是谁知道,Spring 将来可能会增加一些额外的例外。


还有什么?

与上述类似,将来,Spring 可能会基于它们的分层约定为@Service @Controller@Repository @Controller@Repository添加特殊功能。因此,尊重约定并与层配合使用始终是一个好主意。

它们几乎相同 - 所有这些都意味着该类是 Spring bean。 @Service @Controller@Repository@Controller是专用的@Component 。您可以选择对它们执行特定的操作。例如:

  • @Controller bean 由 spring-mvc 使用
  • @Repository bean 有资格进行持久性异常翻译

另一件事是您在语义上将组件指定给不同的层。

@Component提供的一件事是,您可以用它注释其他注释,然后以与@Service相同的方式使用它们。

例如最近我做了:

@Component
@Scope("prototype")
public @interface ScheduledJob {..}

因此,所有带有@ScheduledJob注释的类都是 spring bean,除此之外,它们都注册为石英作业。您只需要提供处理特定注释的代码即可。

@Component 等效于

<bean>

@ Service,@ Controller,@ Repository = {@Component + 一些其他特殊功能}

这意味着服务,控制器和存储库在功能上是相同的。

这三个注释用于在应用程序中分隔“层”

  • 控制器只是执行诸如调度,转发,调用服务方法之类的工作。
  • 服务保留业务逻辑,计算等
  • 存储库是 DAO(数据访问对象),它们直接访问数据库。

现在您可能会问为什么将它们分开:(我假设您知道面向 AOP 的面向程序设计)

假设您只想监视 DAO 层的活动。您将编写一个 Aspect(A 类)类,该类在调用 DAO 的每个方法之前和之后进行一些日志记录,因为您具有三个不同的层并且没有混合在一起,所以可以使用 AOP 进行记录。

因此,您可以在 DAO 方法 “前后”,“之前” 或 “之后” 记录 DAO。之所以可以这样做,是因为您首先拥有了一个 DAO。您刚刚实现的是关注点或任务分离。

想象一下,如果只有一个 @Controller 注释,那么此组件将具有调度,业务逻辑和访问数据库的所有混合功能,因此代码很脏!

上面提到的是一种非常常见的场景,为什么要使用三个注释还有更多的用例。

在 Spring 中, @Service @Component@Service @Controller@Repository @Controller@Repository@Repository型注释,用于:

@Controller: 从表示页面完成的请求 映射即表示层不会转到任何其他文件,它将直接转到@Controller类并检查@RequestMapping注释中的请求路径,该注释在必要时在方法调用之前编写。

@Service :所有业务逻辑都在这里,即与数据相关的计算和所有。业务层的此批注,我们的用户没有直接调用持久性方法,因此它将使用此批注来调用此方法。 它将根据用户请求请求 @Repository

@Repository :这是应用程序的持久层(数据访问层),用于从数据库中获取数据。即所有与数据库有关的操作都由存储库完成。

@Component Component - 用组件@Component注释其他组件(例如 REST 资源类)。

指示带注释的类是 “ 组件 ”。当使用基于注释的配置和类路径扫描时,此类会被视为自动检测的候选。

其他类级注释也可以被视为标识组件,通常是一种特殊的组件:例如 @Repository 注释或 AspectJ 的 @Aspect 注释。

在此处输入图片说明

Spring 2.5 引入了更多的构造型注释:@ Component,@ Service 和 @Controller。 @Component 用作任何 Spring 托管组件的通用构造型;而 @ Repository,@ Service 和 @Controller 则作为 @Component 的特殊化,用于更具体的用例(例如,分别在持久性,服务和表示层中)。这意味着您可以使用 @Component 来注释组件类,但是通过使用 @ Repository,@ Service 或 @Controller 来注释组件类,您的类更适合通过工具进行处理或与方面相关联。例如,这些构造型注释成为切入点的理想目标。当然,@ Repository,@ Service 和 @Controller 也可能在 Spring 框架的将来版本中带有其他语义。因此,如果您决定在服务层使用 @Component 还是 @Service 之间进行选择,则 @Service 显然是更好的选择。同样,如上所述,@ Repository 已被支持作为持久层中自动异常转换的标记。

@Component – Indicates a auto scan component.
@Repository – Indicates DAO component in the persistence layer.
@Service – Indicates a Service component in the business layer.
@Controller – Indicates a controller component in the presentation layer.

参考: -Spring 文档 - 使用 Java 进行类路径扫描,托管组件和编写配置

使用@Service@Repository注解是从数据库连接的角度很重要。

  1. @Service用于所有 Web 服务类型的数据库连接
  2. 对所有存储的 proc DB 连接使用@Repository

如果未使用正确的注释,则可能会遇到由回滚事务覆盖的提交异常。在压力负载测试期间,您将看到与回滚 JDBC 事务相关的异常。

从技术上讲, @Service@Repository @Controller@Service @Repository都是相同的。它们都扩展了@Component

从 Spring 源代码:

指示带注释的类是 “组件”。当使用基于注释的配置和类路径扫描时,此类会被视为自动检测的候选。

我们可以为每个 bean 直接使用@Component ,但是为了更好地理解和维护大型应用程序,我们使用@Controller @Service@Repository @Controller@Repository

每个注释的目的:

  1. @Controller > 带有注释的类旨在接收来自客户端的请求。第一个请求到达 Dispatcher Servlet,在此它使用@RequestMapping批注的值将请求传递到特定的控制器。
  2. @Service > 带有此注释的类旨在处理我们从客户端接收或从数据库获取的数据。所有对数据的操作都应在此层中完成。
  3. @Repository > 带有注释的类旨在与数据库连接。也可以将其视为 DAO(数据访问对象)层。该层应仅限于 CRUD(创建,检索,更新,删除)操作。如果需要任何操作,则应将数据发送回 @Service 层。

如果我们交换它们的位置(使用@Repository代替@Controller ),我们的应用程序将正常运行。

使用三种不同的@annotations的主要目的是为 Enterprise 应用程序提供更好的模块化。

@Repository @Service@Controller用作 @Component 的特殊化,在此基础上,您可以将 @Service 替换为 @Component,但在这种情况下,您会松散特殊化。

1. **@Repository**   - Automatic exception translation in your persistence layer.
2. **@Service**      - It indicates that the annotated class is providing a business service to other layers within the application.

所有这些注释都是立体类型的注释类型,这三个注释之间的区别是

  • 如果我们添加 @Component,则它告诉类的角色是组件类,这意味着它是由某种逻辑组成的类,但是它不能告诉类是否包含特定的业务或持久性或控制器逻辑,因此我们不使用直接将此 @Component 批注
  • 如果我们添加 @Service 批注,那么它将说明由业务逻辑组成的类的角色
  • 如果我们在类的顶部添加 @Repository,则它表明包含持久性逻辑的类
  • 这里 @Component 是 @ Service,@ Repository 和 @Controller 批注的基本批注

例如

package com.spring.anno;
@Service
public class TestBean
{
    public void m1()
    {
       //business code
    }
}

package com.spring.anno;
@Repository
public class TestBean
{
    public void update()
    {
       //persistence code
    }
}
  • 每当我们默认情况下添加@Service@Repositroy@Controller注释时, @Component注释将存在于类顶部