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


能够 @Component@Repository 和 @Service 注释在Spring中可以互换使用,还是除了作为符号设备之外还提供任何特定的功能?

换句话说,如果我有一个Service类并且我更改了注释 @Service 至 @Component,它仍然会以同样的方式行事吗?

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


1523
2017-07-26 09:10


起源


作为一名具有Microsoft背景的开发人员,我回忆起旧的MS SmartClientSoftwareFactory框架中的服务的语义定义(现在是分布式桌面应用程序的一个长期弃用的复杂框架)。那个定义(很好地记录 作者:Rich Newman)将服务定义为无状态可重用对象,最好使用单例作用域,用于对作为参数传递的其他对象执行业务逻辑操作。我倾向于以同样的方式查看Spring服务 - Ivaylo Slavov
没关系!!什么对你有用:)我一直讨厌Spring,他们总是倾向于为你定义“规则”,这只会为你的应用程序增加琐碎的价值。更不用说Spring带有自己的巨大堆栈。 - TriCore
@TriCore Sprting是一个框架,为你定义“规则”就是它的工作:) - Walfrat


答案:


Spring文档

在Spring 2.0及更高版本中 @Repository 注释是一个标记   任何履行角色或刻板印象的类(也称为数据   存储库的Access Object或DAO)。这个标记的用途之一   是例外的自动翻译。

Spring 2.5引入了进一步的构造型注释: @Component,    @Service,和 @Controller@Component 对任何人都是一种通用的刻板印象   Spring管理的组件。 @Repository@Service,和 @Controller 是   专业化 @Component 对于更具体的用例,   例如,在持久性,服务和表示层中,   分别。

因此,您可以使用注释对组件类进行注释 @Component,   但是用它来注释它们 @Repository@Service, 要么 @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)      │
└────────────┴─────────────────────────────────────────────────────┘

1119
2017-08-01 10:20



将@Controller(或@Component)添加到@WebServlet是否有意义?它不是Spring MVC控制器,但这是概念上最接近的匹配。那么servlet过滤器呢? - Rick
什么“@Repository已被支持作为持久层中自动异常转换的标记。”意思? - Jack
它指的是这些注释是AOP的良好目标这一事实,虽然其他注释尚未定义切入点,但它们可能在将来也会这样做。另一方面,@ Repository目前已经成为切入点的目标。该切入点用于异常转换,即将特定于技术的异常转换为更通用的基于Spring的异常,以避免紧密耦合。 - stivlo
@stivlo:我真的试图理解“刻板印象”一词,但仍然不明白。你能帮我理解这个术语吗?它非常有帮助,非常感谢你 - Premraj
stackoverflow.com/questions/14756486/... - stivlo


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

首先是 相似 

值得再次强调的第一点是 关于BeanDefinition的扫描自动检测和依赖注入 所有这些注释(即@Component,@ Service,   @ Repository,@ Controller)是一样的。 我们可以使用一个   另一个,仍然可以解决我的方式。


@ Component,@ Repository,@ Controller和@Service之间的差异

@零件

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

@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 和 @Repository 是特殊类型的 @Component 注解。 <context:component-scan> 选择它们并将它们的后续类注册为bean,就像它们被注释一样 @Component

扫描它们是因为它们本身都带有注释 @Component 注解。如果我们定义自己的自定义注释并使用它进行注释 @Component,然后它也将被扫描 <context:component-scan>


@Repository

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

@Repository有什么特别之处? 

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

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

这个bean后处理器为任何带注释的bean添加了一个顾问程序 @Repository 这样任何特定于平台的异常都会被捕获,然后作为Spring未经检查的数据访问异常之一重新抛出。


@Controller

@Controller 注释表示特定类充当控制器的角色。该 @Controller 注释充当带注释的类的构造型,指示其角色。

@Controller有什么特别之处? 

我们无法将此注释切换为任何其他类似注释 @Service 要么 @Repository,即使它们看起来一样。 调度程序扫描带注释的类 @Controller 并检测到 @RequestMapping 其中的注释。我们只能使用 @RequestMapping 上 @Controller 带注释的类。


@服务

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

@Service有什么特别之处? 

除了它用于表明它持有业务逻辑这一事实之外,这个注释没有明显的特点,但是谁知道,spring可能在未来增加一些额外的特殊功能。


还有什么?

与上面类似,未来Spring可能会选择添加特殊功能 @Service@Controller 和 @Repository 基于他们的分层约定。因此,尊重惯例并将其与层一致使用始终是一个好主意。


426
2017-07-24 06:43



这是我的最爱。这个问题有很多好的答案,我鼓励你们阅读所有这些,但这强调了注释之间的差异。 - Adrian Cosma
很简短的解释 - VedX
没有言语可以赞赏这个答案。每一个陈述都清晰易懂。 - MAC
这里给出的解释简明扼要。这是我迄今为止唯一令人满意的答案 - Julius Krah
这就是答案。 - Alessandro


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

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

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

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

例如最近我做了:

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

所以所有类都注明了 @ScheduledJob 是春豆,除此之外还注册为石英工作。您只需提供处理特定注释的代码即可。


388
2017-07-26 09:16



@Component只是一个spring bean,还有其他任何用途吗? - kapil das
弹簧容器可以自动检测@Component bean。您不需要在配置文件中定义bean,它将在运行时由Spring自动检测。 - Akash5288
我非常喜欢通用的@Component ...特别是在与@Scope的组合中(proxyMode = ScopedProxyMode.//MODE) - Eddie B


@Component相当于

<bean>

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

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

这三个注释用于分隔 “图层” 在你的申请中,

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

现在您可能会问为什么将它们分开:(我假设你知道AOP-Aspect Oriented Programming)

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

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

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

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


333
2018-05-23 05:15



我有一个基本问题 - 弹簧机制使用的注释还是程序员只记住这些代码的作用? - user107986
@ user107986它们主要供程序员记住应用程序中的图层。然而 @Respository 还具有自动异常翻译功能。就像在a中发生异常一样 @Repository 通常有一个处理程序用于该异常,并且不需要在DAO类中添加try catch块。它与PersistenceExceptionTranslationPostProcessor一起使用 - Oliver
你能不能写一个示例代码来编写所有“@Repository”类的联合点。我们要么使用表达式,要么使用bean名称,但是我们怎么能说这个建议将适用于所有“@Repository”类。我试图得到这个样本但却无法找到。你的帮助真的很感激。 - Moni
此外,尽管注释当前在功能上都是相同的,但是将来可能会添加给定属性的特定功能。 - Cod3Citrus


在春天 @Component@Service@Controller,和 @Repository 是Stereotype注释,用于:

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

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

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

@Component  - 使用组件构造型注释您的其他组件(例如REST资源类)。

表示带注释的类是“零件“这样的课程是   被认为是使用时自动检测的候选者   基于注释的配置和类路径扫描。

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

enter image description here


188
2018-03-25 08:00



这些答案都很好,但我非常清楚我们大多数人想要的是一些代码示例,其中包括服务提供的组件,我们可以更具体地放在我们的头脑中,而不仅仅是像“业务逻辑”这样的一般描述属于这个对象。否则,我们仍然假设“哦,这很好,除了我仍然可以将相同的代码应用于组件” - dtc
不 所有 业务逻辑应该进入服务!就DDD而言,服务应仅包含影响多个实体的域逻辑。见答案 stackoverflow.com/a/41358034/238134 - deamon
@deamon是的,但它取决于开发人员的方法 - Harshal Patil
@HarshalPatil当然,您可以在服务中编写一个包含所有业务逻辑的应用程序,但这会导致一个贫乏的域模型,这将使​​得在实体上强制实施约束和一致性变得不必要。 - deamon


Spring 2.5引入了更多的构造型注释:@ Component,@ Service和@Controller。 @Component作为任何Spring管理组件的通用构造型;而@Repository,@ Service和@Controller用作更具体用例的@Component的特化(例如,分别在持久性,服务和表示层中)。这意味着您可以使用@Component注释组件类,但是通过使用@ Repository,@ Service或@Controller注释它们,您的类更适合通过工具处理或与方面关联。例如,这些刻板印象注释成为切入点的理想目标。当然,在Spring Framework的未来版本中,@ Repository,@ Service和@Controller也可能带有额外的语义。因此,如果您在为服务层使用@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进行类路径扫描,托管组件和编写配置  


59
2018-05-15 12:48





@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.  

你会注意到所有 @Repository@Service 要么 @Controller 用...注释 @Component。那么,我们可以使用吗? @Component 用于自动扫描的所有组件?是的,你可以,Spring会自动扫描@Component注释的所有组件。

它工作正常,但不是一个好的做法,为了便于阅读,你应该总是声明 @Repository@Service 要么 @Controller 对于指定的图层,使您的代码更容易阅读。


51
2017-12-16 18:10





用于 @Service 和 @Repository 从数据库连接的角度来看,注释很重要。

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

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


40
2017-11-02 16:05





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

这些刻板印象之间的主要区别在于它们用于不同的分类。

在多层应用程序中,我们将有不同的层,如表示,服务,业务,数据访问等。当一个类要注释为Spring自动检测时,我们应该使用相应的原型如下。

@Component  - 通用的,可以跨应用程序使用。
@Service  - 在服务层级注释类。
@Repository  - 在持久层注释类,它将充当数据库存储库。

如果从技术上讲它们将是相同的,那么为什么我们需要在不同的层级使用它们。为什么不在所有层使用相同的。例如,如果我们使用 @Service 在所有层中,所有bean都将被实例化并且没有问题。例如,考虑到一个小的差异 @Repository

后处理器自动查找所有异常转换器(PersistenceExceptionTranslator接口的实现)并建议所有标记为 @Repository 注释,以便发现的翻译人员可以拦截并对抛出的异常应用适当的翻译。

与上述类似,未来Spring可能会选择为其增值 @Service@Controller 和 @Repository 基于他们的分层约定。对于该附加特征的优点,它更好地遵守惯例并且与层一起使用它们。

除了上述之外,关于扫描自动检测,BeanDefinition的依赖注入 @Component@Service@Repository@Controller 是一样的。


31
2017-10-10 08:11





@Repository  @服务 和 @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.

24
2017-07-18 11:23





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

  • 如果我们添加@Component然后它告诉class的类是一个组件类,它意味着它是一个包含一些逻辑的类,但它   不会告诉某个类是否包含特定的业务或   持久性或控制器逻辑,所以我们不直接使用它   @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 注释将在课堂上存在

23
2018-04-25 16:19