繁体   English   中英

Spring 中的@Component、@Repository 和@Service 注解有什么区别?

[英]What's the difference between @Component, @Repository & @Service annotations in Spring?

@Component@Repository@Service注释可以在 Spring 中互换使用吗?或者它们是否提供除了充当符号设备之外的任何特定功能?

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

或者注释是否也会影响类的行为和功能?

来自Spring 文档

@Repository注释是任何满足存储库角色或构造型(也称为数据访问对象或 DAO)的类的标记。 此标记的用途之一是异常的自动转换,如异常转换中所述

Spring 提供了更多的@Component型注解: @Component@Service @Controller@Controller @Component是任何 Spring 管理的组件的通用@Component型。 @Repository@Service@Controller@Component的特化,用于更具体的用例(分别在持久层、服务层和表示层)。 因此,您可以使用@Component注释您的组件类,但是,通过使用@Repository@Service@Controller注释它们,您的类更适合由工具处理或与方面相关联。

例如,这些构造型注释是切入点的理想目标。 @Repository@Service@Controller还可以在 Spring Framework 的未来版本中携带额外的语义。 因此,如果您在服务层使用@Component@Service之间做出选择, @Service Service 显然是更好的选择。 同样,如前所述, @Repository已经被支持作为持久层中自动异常转换的标记。

注解 意义
@Component 任何 Spring 管理的组件的通用构造型
@Repository 持久层的构造型
@Service 服务层的构造型
@Controller 表示层的构造型(spring-mvc)

由于许多答案已经说明了这些注释的用途,我们在这里将重点讨论它们之间的一些细微差别。

首先是相似性

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


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

@成分

这是一个通用构造型注释,表明该类是一个弹簧组件。

@Component 有什么特别之处
<context:component-scan>只扫描@Component ,一般不查找@Controller@Service@Repository 它们被扫描是因为它们本身是用@Component注释的。

只需看看@Controller@Service@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

这是为了表明该类定义了一个数据存储库。

@Repository 有什么特别之处?

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

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

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


@控制器

@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添加特殊功能。 因此,尊重约定并将其与层一起使用总是一个好主意。

它们几乎相同——所有这些都意味着该类是一个 Spring bean。 @Service@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-Aspect Oriented Programming)

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

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

试想如果只有一个注解@Controller,那么这个组件的调度、业务逻辑和访问数据库都是混杂的,好脏的代码!

上面提到的是一种很常见的场景,关于为什么要使用三个注解的用例还有很多。

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

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

@Service :所有的业务逻辑都在这里,即数据相关的计算和所有。业务层的这个注解,我们的用户不直接调用持久化方法,所以它会使用这个注解调用这个方法。 它将根据用户请求请求@Repository

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

@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 Framework 的未来版本中携带额外的语义。 因此,如果您在为服务层使用 @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 进行类路径扫描、托管组件和编写配置

从技术上讲@Controller@Service@Repository都是一样的。 所有这些都扩展了@Component

从 Spring 源代码:

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

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

每个注解的目的:

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

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

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

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

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

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

@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注释就会存在于类之上

Spring 提供了四种不同类型的自动组件扫描注解,它们是@Component@Service@Repository@Controller 从技术上讲,它们之间没有区别,但是每个自动组件扫描注释都应用于特殊目的并在定义的层内使用。

@Component :它是一个基本的自动组件扫描注释,它表明被注释的类是一个自动扫描组件。

@Controller :注解类表示它是一个控制器组件,主要用于表现层。

@Service :表示注解类是业务层的Service组件。

@Repository :您需要在持久层中使用此注释,这就像数据库存储库。

在注释他们的类时,应该选择一种更专业的@Component形式,因为此注释可能包含未来的特定行为。

@Component@Service@Controller@Repository之间没有区别。 @Component是表示我们 MVC 组件的通用注解。 但是将有几个组件作为我们 MVC 应用程序的一部分,如服务层组件、持久层组件和表示层组件。 所以为了区分它们,Spring 人们也给了其他三个注释。

  • 表示持久层组件: @Repository
  • 表示服务层组件: @Service
  • 表示表示层组件: @Controller
  • 否则你可以对所有这些使用@Component

我们可以根据java标准回答这个

参考 Spring 现在支持的JSR-330 ,您只能使用@Named来定义一个 bean(不知何故@Named=@Component )。 所以根据这个标准,似乎没有用定义@Repository型(如@Repository@Service@Controller )来分类 bean。

但是 spring 用户这些不同的注解在不同的用于具体的用途,例如:

  1. 帮助开发者为胜任者定义更好的类别。 在某些情况下,这种分类可能会有所帮助。 (例如,当您使用aspect-oriented ,这些可能是pointcuts的良好候选者)
  2. @Repository注释将为您的 bean 添加一些功能(一些自动异常转换到您的 bean 持久层)。
  3. 如果您使用的是 spring MVC,则只能将@RequestMapping添加到由@Controller注释的类中。

使用 @Component 注释其他组件,例如 REST 资源类。

@Component
public class AdressComp{
    .......
    ...//some code here    
}

@Component 是任何 Spring 托管组件的通用构造型。

@Controller、@Service 和@Repository 是@Component 针对特定用例的特化。

春天的@Component

“组件专业化”

即使我们交换@Component 或@Repository 或@service

它的行为是相同的,但一方面是如果我们使用组件或@service,它们将无法捕获与 DAO 而不是 Repository 相关的某些特定异常。

@Component :您注释一个类@Component ,它告诉 hibernate 它是一个 Bean。

@Repository :您注释一个类@Repository ,它告诉 hibernate 它是一个 DAO 类并将其视为 DAO 类。 意味着它使未经检查的异常(从 DAO 方法抛出)有资格转换为 Spring DataAccessException

@Service :这告诉 hibernate 它是一个 Service 类,您将在其中拥有@Transactional等服务层注释,因此 hibernate 将其视为服务组件。

加上@Service@Component进步。 假设 bean 类名为CustomerService ,因为您没有选择 XML bean 配置方式,所以您使用@Component对 bean 进行注释以指示它是一个 Bean。 所以在获取 bean 对象CustomerService cust = (CustomerService)context.getBean("customerService"); 默认情况下,Spring 将小写组件的第一个字符——从“CustomerService”到“customerService”。 您可以检索名称为“customerService”的组件。 但是,如果您对 bean 类使用@Service批注,则可以通过以下方式提供特定的 bean 名称

@Service("AAA")
public class CustomerService{

你可以通过

CustomerService cust = (CustomerService)context.getBean("AAA");

在 Spring 4 中,最新版本:

@Repository 注释是任何满足存储库角色或构造型(也称为数据访问对象或 DAO)的类的标记。 此标记的用途之一是自动转换异常,如第 20.2.2 节“异常转换”中所述。

Spring 提供了更多的构造型注解:@Component、@Service 和 @Controller。 @Component 是任何 Spring 管理的组件的通用构造型。 @Repository、@Service 和@Controller 是@Component 的特化,用于更具体的用例,例如,分别在持久层、服务层和表示层中。 因此,您可以使用@Component 注释您的组件类,但是通过使用@Repository、@Service 或@Controller 来注释它们,您的类更适合由工具处理或与方面相关联。 例如,这些构造型注释是切入点的理想目标。 在 Spring Framework 的未来版本中,@Repository、@Service 和 @Controller 也可能带有额外的语义。 因此,如果您在服务层使用 @Component 或 @Service 之间做出选择,@Service 显然是更好的选择。 同样,如上所述,@Repository 已经被支持作为持久层中自动异常转换的标记。

@Component是顶级通用注解,它使注解的 bean 被扫描并在 DI 容器中可用

@Repository是专门的注解,它带来了转换来自 DAO 类的所有未检查异常的功能

@Service是专门的注解。 它目前没有带来任何新功能,但它阐明了 bean 的意图

@Controller 是专门的注释,它使 bean MVC 意识到并允许使用进一步的注释,如@RequestMapping和所有此类

这里有更多细节

这里有足够好的答案来解释组件存储库服务注释之间的差异。 我想分享@Controller & @RestController之间的区别

@ControllerRestController

@RestController

在此处输入图片说明

  • 这个注解是@Controller一个特殊版本,它自动添加了@Controller@ResponseBody注解。 所以我们不必将@ResponseBody添加到我们的映射方法中。 这意味着@ResponseBody默认处于活动状态。
  • 如果使用@RestController ,则无法返回视图(通过在 Spring/Spring-Boot 中使用Viewresolver
  • @RestController还自动将响应转换为JSON/XML automatically因为@ResponseBody使返回的对象成为可能在正文中的对象, eg JSON or XML

@Controller

在此处输入图片说明

  • @Controller用于将类标记为 Spring MVC 控制器。 这个注解只是@Component一个特殊版本,它允许基于类路径扫描自动检测控制器类。
  • @Controller您可以在 Spring Web MVC 中返回一个视图。

更详细的视图

引用 spring 文档的@Service

表示带注释的类是“服务”,最初由领域驱动设计(Evans,2003)定义为“作为独立于模型中的接口提供的操作,没有封装状态”。 也可能表示一个类是“业务服务外观”(在核心 J2EE 模式意义上)或类似的东西。 此注释是通用的刻板印象,个别团队可能会缩小其语义范围并酌情使用。

如果你看看 eric evans 的领域驱动设计,

SERVICE 是作为独立于模型中的接口提供的操作,没有像 ENTITIES 和 VALUE OBJECTS 那样封装状态。 SERVICES 是技术框架中的常见模式,但它们也可以应用于领域层。 名称服务强调与其他对象的关系。 与 ENTITIES 和 VALUE OBJECTS 不同,它纯粹是根据它可以为客户端做什么来定义的。 SERVICE 往往以活动命名,而不是实体——动词而不是名词。 SERVICE 仍然可以有一个抽象的、有意的定义; 它只是具有与对象定义不同的风味。 一个 SERVICE 仍然应该有一个已定义的职责,并且这个职责和实现它的接口应该被定义为域模型的一部分。 操作名称应来自 UBIQUITOUS LANGUAGE 或引入其中。 参数和结果应该是域对象。 应该明智地使用 SERVICES,不允许剥夺其所有行为的实体和价值对象。 但是,当操作实际上是一个重要的领域概念时,服务就构成了模型驱动设计的自然组成部分。 在模型中声明为 SERVICE,而不是作为实际不代表任何内容的虚假对象,独立操作不会误导任何人。

和 Eric Evans 的Repository

一个 REPOSITORY 将某种类型的所有对象表示为一个概念集(通常是模拟的)。 它就像一个集合,除了具有更复杂的查询功能。 添加和删​​除适当类型的对象,并且 REPOSITORY 背后的机制将它们插入或从数据库中删除。 这个定义收集了一组有凝聚力的责任,用于提供从早期生命周期到结束的对 AGGREGATES 根的访问。

这里提供的答案在技术上是部分正确的,但即使回复列表很长而且这将在底部,我认为也值得在此处放置一个实际正确的回复,以防万一有人偶然发现并从中学到一些有价值的东西它。 并不是其余的答案完全错误,只是它们不正确。 而且,为了阻止成群结队的巨魔,是的,我知道从技术上讲,这些注释现在实际上是同一件事,并且即使到 spring 5 也几乎可以互换。现在,对于正确的答案:

这三个注解是完全不同的东西,不可互换。 你可以这么说,因为它们是三个而不是一个。 它们不打算互换,它们只是为了优雅和方便而实现的。

现代编程是不同比例的发明、艺术、技术和交流。 通信位通常非常重要,因为代码的读取次数通常比编写的次数要多得多。 作为程序员,您不仅要尝试解决技术问题,还要尝试将您的意图传达给阅读您代码的未来程序员。 这些程序员可能不会分享你的母语,也不会分享你的社交环境,他们有可能在未来 50 年阅读你的代码(这并不像你想象的那么不可能)。 很难在那么远的将来进行有效的沟通。 因此,使用我们可用的最清晰、最有效、最正确和可交流的语言至关重要。 我们仔细选择我们的话,以产生最大的影响,并尽可能清楚地表达我们的意图。

例如,在我们编写存储库时使用@Repository而不是@Component是至关重要的。 后者对于存储库来说是一个非常糟糕的注释选择,因为它并不表明我们正在查看存储库。 我们可以假设存储库也是 spring-bean,但不能假设组件是存储库。 使用@Repository ,我们的语言变得清晰而具体。 我们清楚地说明这是一个存储库。 使用@Component我们让读者决定他们正在阅读什么类型的组件,他们将不得不阅读整个类(可能还有子类和接口的树)来推断含义。 在遥远的未来,这个类可能会被读者误解为不是一个存储库,我们应该对这个错误负部分责任,因为我们完全知道这是一个存储库,但未能在我们的语言中具体化并有效地传达我们的意图。

我不会进入其他示例,但会尽可能清楚地说明:这些注释是完全不同的东西,应该根据它们的意图适当地使用。 @Repository用于存储库,没有其他注释是正确的。 @Service用于服务,没有其他注释是正确的。 @Component用于既不是存储库也不是服务的组件,在它的位置使用它们中的任何一个也是不正确的。 它可能会编译,它甚至可能运行并通过您的测试,但这是错误的,如果您这样做,我会(专业地)认为您较少。

整个春天都有这样的例子(以及一般的编程)。 编写 REST API 时不得使用@Controller ,因为@RestController可用。 @GetMapping是有效的替代方案时,您不得使用@RequestMapping 等等等等 你必须选择最具体、准确和正确的语言来向你的读者传达你的意图,否则,你将风险引入你的系统,风险是有代价的。

最后,我想提出一个关于面向对象系统的程序问题。 基本规则之一是实现可以变化,但接口不应该。 假设这些注释是同一个东西是一个非常滑坡并且完全反对 OO。 尽管它们现在可能以可互换的方式实施,但不能保证它们将来会如此。 此外,即使在同一个团队中,工程师也可能决定使用方面将一些行为挂在这些注释中的一个或多个上,或者平台工程师可能出于操作原因选择替换其中一个的实现。 你只是不知道,也不应该——在面向对象中,你依赖于接口,而不是实现。

RepositoryServiceComponent annotation 的子代。 所以,它们都是Component 存储库服务只是扩展它。 具体如何? 服务只有意识形态上的差异:我们将其用于服务。 存储库具有特定的异常处理程序。

刻板印象的解释:

  • @Service - 使用 @Service 注释所有服务类。 这一层知道工作单元。 您所有的业务逻辑都将在服务类中。 一般服务层的方法都包含在事务中。 您可以从服务方法进行多次 DAO 调用,如果一个事务失败,则所有事务都应回滚。
  • @Repository - 使用 @Repository 注释所有 DAO 类。 您所有的数据库访问逻辑都应该在 DAO 类中。
  • @Component - 使用组件@Component注释您的其他组件(例如 REST 资源类)。
  • @Autowired - 让 Spring 使用 @Autowired 注释将其他 bean 自动连接到您的类中。

@Component是任何 Spring 管理的组件的通用@Component型。 @Repository@Service@Controller@Component用于更具体的用例,例如,分别在持久层、服务层和表示层中。

原来在这里回答。

@Component, @Repository, @Controller & @Service 注解的区别

@Component - 通用,可以跨应用程序使用。
@Service – 在服务层级别注释类。
@Controller – 表示层级别的类注释,主要用于 Spring MVC。
@Repository – 在持久层注释类,它将充当数据库存储库。

@Controller = @Component(内部注解)+ 表现层功能
@Service = @Component(内部注解)+ 服务层功能
@Component = 实际组件(Beans)
@Repository = @Component(内部注释)+ 数据层功能(用于处理域 Bean)

在 spring 框架中提供了一些特殊类型的注解,称为构造型注解。 它们如下:-

@RestController- Declare at controller level.
@Controller – Declare at controller level.
@Component – Declare at Bean/entity level.
@Repository – Declare at DAO level.
@Service – Declare at BO level.

上面声明的注解是特殊的,因为当我们将<context:component-scan>到 xxx-servlet.xml 文件中时,spring 会在上下文创建/加载阶段自动创建那些用上面注解注解的类的对象。

@Component@ Repository@ Service@Controller

@Component是 Spring @Repository管理的组件的通用@Repository@Service @Controller@Controller是用于更具体用途的@Component特化:

  • @Repository持久化
  • @Service用于服务和交易
  • @Controller用于 MVC 控制器

为什么在@Component使用@Repository@Service@Controller 我们可以用@Component 标记我们的组件类,但如果我们使用适应预期功能的替代方案。 我们的类更适合每个特定情况下预期的功能。

使用@Repository注释的类具有更好的翻译和可读性错误处理与 org.springframework.dao.DataAccessException。 非常适合实现访问数据的组件(DataAccessObject 或 DAO)。

带有@Controller带注释的类在 Spring Web MVC 应用程序中扮演控制器角色

带有@Service带注释的类在业务逻辑服务、DAO 管理器(门面)和事务处理的示例门面模式中发挥作用

为了简化这个说明,让我们通过用例来考虑技术性,这些注解是用来注入的,正如我字面上所说的“用来注入”,这意味着,如果你知道如何使用依赖注入“DI”并且你应该,那么你会一直寻找这些注解,通过用这些Stereo Types来注解类,你是在通知DI容器扫描它们以准备在其他地方注入,这是实际的目标。

现在让我们移到每一个; 首先@Service ,如果您正在为特定业务案例构建一些逻辑,则需要将其分离在包含您的业务逻辑的地方,该服务是普通类,或者您可以根据需要将其用作接口,它的写法如下这

@Service
public class Doer {
   // Your logic 
}

// To use it in another class, suppose in Controller 
@Controller
public class XController {
 // You have to inject it like this 
 @Autowired 
 private Doer doer;
}

注入的时候都是一样的, @Repository是一个接口,应用了Repository Pattern Repository设计模式的实现,一般在你处理一些数据存储或数据库时使用,你会发现,它包含多个为您准备好处理数据库操作的实现; 它可以是CrudRepositoryJpaRepository等。

// For example
public interface DoerRepository implements JpaRepository<Long, XEntity> {}

最后是@Component ,这是 Spring 中注册 bean 的通用形式,即 spring 一直在寻找标有 @Component 的 bean 进行注册,那么 @Service 和 @Repository 都是 @Component 的特例,但是常见的用例组件是指您制作的东西纯粹是技术性的,而不是为了涵盖直接的业务案例! 如格式化日期或处理特殊请求序列化机制等。

@Component在配置类中充当@Bean 注解,在 spring 上下文中注册 bean。 它也是@Service、@Repository 和@Controller 注释的父级。

@Service ,扩展 @Component 注释并且只有命名差异。

@Repository - 扩展 @Component 注释并将所有数据库异常转换为DataAccessException

@Controller - 在 MVC 模式中充当控制器。 调度程序将扫描这些带注释的类以查找映射方法,检测 @RequestMapping 注释。

Spring 支持@Component、@service、@Repository 等多种类型的注解。 所有论文都可以在 org.springframework.stereotype 包下找到。

当我们的应用程序中的类使用上述任何注释进行注释时,在项目启动期间 spring 扫描(使用 @ComponentScan)每个类并将类的实例注入 IOC 容器。 @ComponentScan 要做的另一件事是运行带有 @Bean 的方法,并将返回对象作为 bean 恢复到 Ioc 容器。

在我们深入研究(@Component vs @service vs @Repository)之前,首先我们必须了解@Bean 和@Component 之间的区别

在此处输入图片说明


@Component vs @Repository vs @Service


在大多数典型的应用程序中,我们有不同的层,如数据访问、表示、服务、业务等。此外,在每一层中,我们都有不同的 bean。 为了自动检测这些 bean,Spring 使用类路径扫描注解。然后它在 ApplicationContext 中注册每个 bean。

以下是其中一些注释的简短概述:

  • @Component 是任何 Spring 管理的组件的通用构造型。
  • @Service 在服务层注释类。
  • @Repository 在持久层注释类,它将充当数据库存储库。

@Component 注解

@Component 是一个类级别的注解。我们可以在整个应用程序中使用@Component 将bean 标记为Spring 的托管组件。 Spring 只会使用@Component 获取和注册 bean,一般不会查找 @Service 和 @Repository。

它们是在 ApplicationContext 中注册的,因为它们是用 @Component 注释的

如前所述,@Component 是所有构造型注释的父级。 当 Spring 执行组件扫描时,它只查找标有 @Component 注解的类。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

我们可以在所有类上使用这个注解,它不会造成任何差异。

@服务注解

我们用@Service 标记bean 以表明它们持有业务逻辑。 除了在服务层使用之外,这个注解没有任何其他特殊用途。

@Service 是组件的子级,用于表示来自应用程序服务层的类。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
   @AliasFor(
       annotation = Component.class
   )
   String value() default "";
}

@Repository 注解

@Repository 的工作是捕获特定于持久性的异常并将它们作为 Spring 的统一未检查异常之一重新抛出。

为此,Spring 提供了 PersistenceExceptionTranslationPostProcessor,我们需要将其添加到我们的应用程序上下文中(如果我们使用 Spring Boot,则已包含):

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

这个 bean 后处理器向任何用 @Repository 注释的 bean 添加了一个顾问。

同样,@Repository 也是组件注解的子类,用于属于持久化数据访问层的类,作为数据存储库。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

概括

@Service 和@Repository 是@Component 的特例。 它们在技术上是相同的,但我们将它们用于不同的目的。根据它们的图层约定选择注释总是一个好主意。

即使它的行为相同,但它利用了许多软件开发原则的应用程序,几个例子是:

- Single Responsibility
- Open Closed Principal 
@Component
@Controller
@Repository
@Service
@RestController

这些都是 StereoType 注释。这对于将我们的类作为 ioc 容器中的 spring bean 很有用,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM