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

后端 未结 29 2204
时光说笑
时光说笑 2020-11-22 00:33

Can @Component, @Repository and @Service annotations be used interchangeably in Spring or do they provide any particular functionality besides acting as a notation device?

相关标签:
29条回答
  • 2020-11-22 00:52

    As many of the answers already state what these annotations are used for, we'll here focus on some minor differences among them.

    First the Similarity

    First point worth highlighting again is that with respect to scan-auto-detection and dependency injection for BeanDefinition all these annotations (viz., @Component, @Service, @Repository, @Controller) are the same. We can use one in place of another and can still get our way around.


    Differences between @Component, @Repository, @Controller and @Service

    @Component

    This is a general-purpose stereotype annotation indicating that the class is a spring component.

    What’s special about @Component
    <context:component-scan> only scans @Component and does not look for @Controller, @Service and @Repository in general. They are scanned because they themselves are annotated with @Component.

    Just take a look at @Controller, @Service and @Repository annotation definitions:

    @Component
    public @interface Service {
        ….
    }
    

     

    @Component
    public @interface Repository {
        ….
    }
    

     

    @Component
    public @interface Controller {
        …
    }
    

    Thus, it’s not wrong to say that @Controller, @Service and @Repository are special types of @Component annotation. <context:component-scan> picks them up and registers their following classes as beans, just as if they were annotated with @Component.

    Special type annotations are also scanned, because they themselves are annotated with @Component annotation, which means they are also @Components. If we define our own custom annotation and annotate it with @Component, it will also get scanned with <context:component-scan>


    @Repository

    This is to indicate that the class defines a data repository.

    What’s special about @Repository?

    In addition to pointing out, that this is an Annotation based Configuration, @Repository’s job is to catch platform specific exceptions and re-throw them as one of Spring’s unified unchecked exception. For this, we’re provided with PersistenceExceptionTranslationPostProcessor, that we are required to add in our Spring’s application context like this:

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

    This bean post processor adds an advisor to any bean that’s annotated with @Repository so that any platform-specific exceptions are caught and then re-thrown as one of Spring’s unchecked data access exceptions.


    @Controller

    The @Controller annotation indicates that a particular class serves the role of a controller. The @Controller annotation acts as a stereotype for the annotated class, indicating its role.

    What’s special about @Controller?

    We cannot switch this annotation with any other like @Service or @Repository, even though they look same. The dispatcher scans the classes annotated with @Controller and detects methods annotated with @RequestMapping annotations within them. We can use @RequestMapping on/in only those methods whose classes are annotated with @Controller and it will NOT work with @Component, @Service, @Repository etc...

    Note: If a class is already registered as a bean through any alternate method, like through @Bean or through @Component, @Service etc... annotations, then @RequestMapping can be picked if the class is also annotated with @RequestMapping annotation. But that's a different scenario.


    @Service

    @Service beans hold the business logic and call methods in the repository layer.

    What’s special about @Service?

    Apart from the fact that it's used to indicate, that it's holding the business logic, there’s nothing else noticeable in this annotation; but who knows, Spring may add some additional exceptional in future.


    What else?

    Similar to above, in the future Spring may add special functionalities for @Service, @Controller and @Repository based on their layering conventions. Hence, it's always a good idea to respect the convention and use it in line with layers.

    0 讨论(0)
  • 2020-11-22 00:52

    The answers presented here are largely technically correct, but even though the response list is long and this will be at the bottom I thought it was worth putting an actually correct response in here too, just in case somebody stumbles upon it and learns something valuable from it. It's not that the rest of the answers are wrong, it's just that they aren't right. And, to stop the hordes of trolls, yes, I know that technically these annotations are effectively the same thing and most interchangeable even unto spring 5. Now, for the right answer:

    These three annotations are completely different things and are not interchangeable. You can tell that because there are three of them rather than just one. They are not intended to be interchangeable, they're just implemented that way out of elegance and convenience.

    Modern programming is invention, art, technique, and communication, in varying proportions. The communication bit is usually very important because code is usually read much more often than its written. As a programmer you're not only trying to solve the technical problem, you're also trying to communicate your intent to future programmers who read your code. These programmers may not share your native language, nor your social environment, and it is possible that they may be reading your code 50-years in the future (it's not as unlikely as you may think). It's difficult to communicate effectively that far into the future. Therefore, it is vital that we use the clearest, most efficient, correct, and communicative language available to us. That we chose our words carefully to have maximum impact and to be as clear as possible as to our intent.

    For example, it is vital that @Repository is used when we're writing a repository, rather than @Component. The latter is a very poor choice of annotation for a repository because it does not indicate that we're looking at a repository. We can assume that a repository is also a spring-bean, but not that a component is a repository. With @Repository we are being clear and specific in our language. We are stating clearly that this is a repository. With @Component we are leaving it to the reader to decide what type of component they are reading, and they will have to read the whole class (and possibly a tree of subclasses and interfaces) to infer meaning. The class could then possibly be misinterpreted by a reader in the distant future as not being a repository, and we would have been partially responsible for this mistake because we, who knew full well that this is a repository, failed to be specific in our language and communicate effectively our intent.

    I won't go into the other examples, but will state as clearly as I can: these annotations are completely different things and should be used appropriately, as per their intent. @Repository is for storage repositories and no other annotation is correct. @Service is for services and no other annotation is correct. @Component is for components that are neither repositories nor services, and to use either of these in its place would also be incorrect. It might compile, it might even run and pass your tests, but it would be wrong and I would think less of you (professionally) if you were to do this.

    There are examples of this throughout spring (and programming in general). You must not use @Controller when writing a REST API, because @RestController is available. You must not use @RequestMapping when @GetMapping is a valid alternative. Etc. Etc. Etc. You must chose the most specific exact and correct language you can to communicate your intent to your readers, otherwise, you are introducing risks into your system, and risk has a cost.

    Thank you for your up-votes :)

    0 讨论(0)
  • 2020-11-22 00:53

    @Component is equivalent to

    <bean>
    

    @Service, @Controller, @Repository = {@Component + some more special functionality}

    That mean Service, The Controller and Repository are functionally the same.

    The three annotations are used to separate "Layers" in your application,

    • Controllers just do stuff like dispatching, forwarding, calling service methods etc.
    • Service Hold business Logic, Calculations etc.
    • Repository are the DAOs (Data Access Objects), they access the database directly.

    Now you may ask why separate them: (I assume you know AOP-Aspect Oriented Programming)

    Let's say you want to Monitors the Activity of the DAO Layer only. You will write an Aspect (A class) class that does some logging before and after every method of your DAO is invoked, you are able to do that using AOP as you have three distinct Layers and are not mixed.

    So you can do logging of DAO "around", "before" or "after" the DAO methods. You could do that because you had a DAO in the first place. What you just achieved is Separation of concerns or tasks.

    Imagine if there were only one annotation @Controller, then this component will have dispatching, business logic and accessing database all mixed, so dirty code!

    Above mentioned is one very common scenario, there are many more use cases of why to use three annotations.

    0 讨论(0)
  • 2020-11-22 00:55

    Even if we interchange @Component or @Repository or @service

    It will behave the same , but one aspect is that they wont be able to catch some specific exception related to DAO instead of Repository if we use component or @ service

    0 讨论(0)
  • 2020-11-22 00:56

    @Component acts as @Bean annotation in configuration class , register bean in spring context. Also it is parent for @Service, @Repository and @Controller annotation.

    @Service, extends @Component annotation and has only naming difference.

    @Repository - extends @Component annotation and translate all database exceptions into DataAccessException.

    @Controller - acts as controller in MVC pattern. The dispatcher will scan such annotated classes for mapped methods, detecting @RequestMapping annotations.

    0 讨论(0)
  • 2020-11-22 00:57

    @Component is the top level generic annotation which makes the annotated bean to be scanned and available in the DI container

    @Repository is specialized annotation and it brings the feature of converting all the unchecked exceptions from the DAO classes

    @Service is specialized annotation. it do not bring any new feature as of now but it clarifies the intent of the bean

    @Controller is specialized annotation which makes the bean MVC aware and allows the use of further annotation like @RequestMapping and all such

    Here are more details

    0 讨论(0)
提交回复
热议问题