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

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

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


当前回答

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

参考JSR-330,它现在被spring支持,您只能使用@Named来定义bean(不知何故,@Named=@Component)。因此,根据这个标准,似乎没有必要为类别bean定义原型(如@Repository、@Service、@Controller)。

但是spring用户在这些不同的注释中有不同的特定用途,例如:

帮助开发人员为胜任者定义更好的类别。这种分类在某些情况下可能会有所帮助。(例如,当您使用面向方面的时,这些可能是切入点的好候选)@存储库注释将为bean添加一些功能(为bean持久层添加一些自动异常转换)。如果您使用的是springMVC,则@RequestMapping只能添加到由@Controller注释的类中。

其他回答

@Component、@Repository、@Controller和@Service注释之间的差异

@组件–通用,可跨应用程序使用@服务–在服务层级别注释类@控制器–注释表示层级别的类,主要用于SpringMVC。@Repository–在持久层注释类,它将充当数据库存储库。

@控制器=@Component(内部注释)+表示层功能@服务=@Component(内部注释)+服务层功能@分量=实际分量(豆类)@Repository=@Component(内部注释)+数据层特性(用于处理域bean)

刻板印象的解释:

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

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

最初在这里回答。

这里给出的答案在技术上是部分正确的,但即使答案列表很长,这将是底部,我认为在这里也应该给出一个真正正确的答案,以防有人偶然发现并从中学习到有价值的东西。这并不是说其余的答案完全错误,只是它们不正确。而且,为了阻止成群的巨魔,是的,我知道,从技术上讲,这些注释现在实际上是一样的,甚至到第5春,它们都可以互换。现在,对于正确的答案:

这三种注释是完全不同的,不可互换。你可以这么说,因为他们有三个而不是一个。它们并不是可互换的,它们只是出于优雅和方便而实现的。

现代编程是不同比例的发明、艺术、技术和通信。通信位通常非常重要,因为代码的读取频率通常比编写频率高得多。作为一名程序员,你不仅试图解决技术问题,还试图将你的意图传达给阅读你代码的未来程序员。这些程序员可能既不共享您的母语,也不共享您所处的社交环境,而且他们可能在未来50年内阅读您的代码(这并不像您想象的那样不可能)。在未来很难有效地沟通。因此,我们必须使用最清晰、最有效、最正确、最具交际能力的语言。我们谨慎地选择词汇,以产生最大的影响,并尽可能清楚地表达我们的意图。

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

我将不讨论其他示例,但将尽可能清楚地说明:这些注释是完全不同的东西,应根据其意图适当使用@存储库用于存储存储库,其他注释都不正确@服务用于服务,其他注释不正确@控制器适用于既不是存储库也不是服务的组件,在其位置使用其中任何一个都是不正确的。它可能会编译,甚至可能运行并通过您的测试,但这是错误的,如果您这样做的话,我会对您(专业)的评价降低。

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

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

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

参考JSR-330,它现在被spring支持,您只能使用@Named来定义bean(不知何故,@Named=@Component)。因此,根据这个标准,似乎没有必要为类别bean定义原型(如@Repository、@Service、@Controller)。

但是spring用户在这些不同的注释中有不同的特定用途,例如:

帮助开发人员为胜任者定义更好的类别。这种分类在某些情况下可能会有所帮助。(例如,当您使用面向方面的时,这些可能是切入点的好候选)@存储库注释将为bean添加一些功能(为bean持久层添加一些自动异常转换)。如果您使用的是springMVC,则@RequestMapping只能添加到由@Controller注释的类中。

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

@服务,扩展了@Component注释,只有命名差异。

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

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