spring @Service 注释应该保存在哪里?接口还是实现?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16351780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:56:06  来源:igfitidea点击:

Where should @Service annotation be kept? Interface or Implementation?

springservice

提问by TheKojuEffect

I'm developing an application using Spring. I'm required to use the @Serviceannotation. I have ServiceIand ServiceImplsuch that ServiceImpl implements ServiceI. I'm confused here as to where should I keep the @Serviceannotation.

我正在使用 Spring 开发应用程序。我需要使用@Service注释。我ServiceIServiceImpl这样ServiceImpl implements ServiceI。我在这里很困惑我应该在哪里保留@Service注释。

Should I annotate the interface or the implementation with @Service? What are the differences between these two approaches?

我应该用 注释接口还是实现@Service?这两种方法有什么区别?

回答by Ralph

I never put @Component(or @Service, ...) at an interface, because this make the interface useless. Let me explain why.

我从不把@Component(or @Service, ...) 放在接口上,因为这会使接口变得无用。让我解释一下原因。

claim 1:If you have an interface then you want to use that interface for the injection point type.

声明 1:如果您有一个接口,那么您想将该接口用于注入点类型。

claim 2:The purpose of an interface is that it define a contract that can been implemented by several implementations. On the other side you have your injection point (@Autowired). Having just one interface and only one class that implement it, is (IMHO) useless, and violates YAGNI.

声明 2:接口的目的是定义一个可以由多个实现实现的契约。在另一侧,您有注射点 ( @Autowired)。只有一个接口和一个实现它的类是(恕我直言)没用的,并且违反了YAGNI

fact:When you put:

事实:当你把:

  • @Component(or @Service, ...) at an interface,
  • have multiple classes that implements it,
  • at least two classes become Spring Beans, and
  • have an injection point that use the interface for type based injection,
  • @Component(或@Service, ...) 在一个界面上,
  • 有多个实现它的类,
  • 至少有两个类成为 Spring Beans,并且
  • 有一个使用接口进行基于类型的注入的注入点,

then you will get and NoUniqueBeanDefinitionException(or you have a very special configurations setup, with Environment, Profiles or Qualifiers ...)

然后你会得到和NoUniqueBeanDefinitionException(或者你有一个非常特殊的配置设置,包括环境、配置文件或限定符......)

Conclusion:If you use @Component(or @Service, ...) at an interface then you must violate at least one of the two clains. Therefore I think it is not useful (except some rare scenarios) to put @Componentat interface level.

结论:如果您在接口上使用@Component(or @Service, ...) 那么您必须至少违反两个声明中的一个。因此我认为放在@Component接口级别是没有用的(除了一些罕见的场景)。



Spring-Data-JPA Repository interfaces are something complete different

Spring-Data-JPA Repository 接口是完全不同的东西

回答by Paulius Matulionis

Basically annotations like @Service, @Repository, @Component, etc. they all serve the same purpose:

基本上像@Service@Repository@Component等注释,它们都有相同的目的:

auto-detection when using annotation-based configuration and classpath scanning.

使用基于注解的配置和类路径扫描时的自动检测。

From my experience I am always using @Serviceannotation on the interfaces or abstract classes and annotations like @Componentand @Repositoryfor their implementation. @Componentannotation I am using on those classes which serves basic purposes, simple Spring beans, nothing more. @Repositoryannotation I am using in the DAOlayer, for e.g. if I have to communicate to the database, have some transactions, etc.

从我的经验我一直使用@Service的接口或抽象类和注释像注释@Component,并@Repository组织落实。@Component我在那些服务于基本目的的类上使用的注释,简单的 Spring bean,仅此而已。@Repository我在DAO层中使用的注释,例如,如果我必须与数据库通信,进行一些事务等。

So I would suggest to annotate your interface with the @Serviceand other layers depending on the functionality.

因此,我建议@Service根据功能使用和其他层来注释您的界面。

回答by yalkris

I used @Component, @Service, @Controllerand @Repositoryannotations only on the implementation classes and not on the interface. But @Autowiredannotation with Interfaces still worked for me.

我用@Component@Service@Controller@Repository注解只在实现类,而不是接口。但是@Autowired带有接口的注释仍然对我有用。

回答by Kuldeep Tiwari

Pros of putting annotation on @Service is that it gives a hint that it is a service. I don't know if any implementing class will by default inherit this annoation.

在@Service 上添加注释的优点是它暗示它是一项服务。我不知道是否有任何实现类会默认继承这个注解。

Con side is that you are coupling your interface with a specific framework i.e. Spring, by using spring specific annotation. As interfaces are supposed to be decoupled from implementation, I would not suggest using any framework specific Annotations or object part of your interface.

缺点是您通过使用特定于 spring 的注释将您的界面与特定框架(即 Spring)耦合。由于接口应该与实现分离,我不建议使用任何框架特定的注释或接口的对象部分。

回答by Fran?ois F.

One benefit of spring is to easily switch Service (or other) implementation. For this, you need to annotate on the interface and declare variable like this :

spring 的一个好处是可以轻松切换 Service(或其他)实现。为此,您需要在接口上进行注释并像这样声明变量:

@Autowired
private MyInterface myVariable;

and not :

并不是 :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

Like the first case, you can activate which implementation to inject from the moment it is unique (only one class implements the interface). In the second case, you need to refactor all your code (the new class implementation has another name). As a consequence, the annotation needs to be on the interface as much as possible. Furthermore, JDK proxies are well suited for this : they are created and instantiated at application startup because runtime type is known by advance, contrary to CGlib proxies.

与第一种情况一样,您可以从唯一的那一刻起激活要注入的实现(只有一个类实现了接口)。在第二种情况下,您需要重构所有代码(新的类实现有另一个名称)。因此,注释需要尽可能多地位于界面上。此外,JDK 代理非常适合于此:它们是在应用程序启动时创建和实例化的,因为运行时类型是预先知道的,这与 CGlib 代理相反。

回答by user1239403

I would put @Serviceon your class but put the name of the interface as a parameter to the annotation e.g.

我会穿上@Service你的课,但把接口的名称作为注释的参数,例如

interface ServiceOne {}

@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}

By doing that you get all the benefits and can still inject the interface but get the class

通过这样做,您可以获得所有好处,并且仍然可以注入接口但获得类

@Autowired 
private ServiceOne serviceOne;

So your interface is not tied to spring framework and you can change the class at any time and not have to update all your injection points.

因此,您的界面与 spring 框架无关,您可以随时更改类,而不必更新所有注入点。

So if I wanted to change the implementation class I could just annotate the new class and remove from the first but that's all that is required to be changed. If you inject the class you could have a lot of work when ever you want to change the impl class.

因此,如果我想更改实现类,我可以注释新类并从第一个类中删除,但这就是需要更改的全部内容。如果您注入该类,那么当您想要更改 impl 类时,您可能需要做很多工作。

回答by HughParker

To put it simply:

简而言之:

@Serviceis a Stereotype annotation for the servicelayer.

@Service服务层的 Stereotype 注解。

@Repos-itoryis a Stereotype annotation for the persis-tencelayer.

@Repos-itory持久层的 Stereotype 注释。

@Componentis a genericstereotype annotation used to tell Spring to create an instance of the object in the Appl-ication Context. It's possible to define any name for the instance, the default is the class name as camel case.

@Component是一个通用构造型注解,用于告诉 Spring 在应用程序上下文中创建对象的实例。可以为实例定义任何名称,默认为驼峰式的类名。

回答by Artur Yolchyan

There are 5 annotations which could be used for making spring beans. List in below of answers.

有5个注释可用于制作春豆。在下面列出答案。

Do you really need an interface? If you are going to have one implementation for each service interface, just avoid it, use only class. Of course, if you don't have RMI or when interface proxy is required.

你真的需要一个接口吗?如果您打算为每个服务接口实现一个,请避免它,只使用类。当然,如果您没有 RMI 或需要接口代理时。

@Repository - use for injecting your dao layer classes.

@Repository - 用于注入您的 dao 层类。

@Service - use for injecting your service layer classes. In service layer also you might need to use @Transactional annotation for db transaction management.

@Service - 用于注入您的服务层类。在服务层中,您可能还需要使用 @Transactional 注释进行数据库事务管理。

@Controller - use for your frontend layer controllers, such as JSF managed beans injecting as spring beans.

@Controller - 用于前端层控制器,例如作为 spring bean 注入的 JSF 托管 bean。

@RestController - use for spring rest controllers, this would help you to avoid every time to put @ResponseBody and @RequestBody annotations in your rest methods.

@RestController - 用于弹簧休息控制器,这将帮助您避免每次在您的休息方法中放置 @ResponseBody 和 @RequestBody 注释。

@Component - use it in any other case when you need to Inject spring bean which is not controller, service, or dao class

@Component - 当您需要注入不是控制器、服务或 dao 类的 spring bean 时,在任何其他情况下使用它