What’s the difference between @Component, @Repository and @Service annotations in Spring? Can @Component, @Repository, and @Service annotations be used interchangeably in Spring or do they provide any particular functionality besides acting as a notation device? In other words, if I ...
Basics The base interface you choose for your repository has two main purposes. First, you allow the Spring Data repository infrastructure to find your interface and trigger the proxy creation so that you inject instances of the interface into clients. The second purpose is to pull in as much functiRead more
Basics
The base interface you choose for your repository has two main purposes. First, you allow the Spring Data repository infrastructure to find your interface and trigger the proxy creation so that you inject instances of the interface into clients. The second purpose is to pull in as much functionality as needed into the interface without having to declare extra methods.
The common interfaces
The Spring Data core library ships with two base interfaces that expose a dedicated set of functionalities:
CrudRepository
– CRUD methodsPagingAndSortingRepository
– methods for pagination and sorting (extendsCrudRepository
)
Store-specific interfaces
The individual store modules (e.g. for JPA or MongoDB) expose store-specific extensions of these base interfaces to allow access to store-specific functionality like flushing or dedicated batching that take some store specifics into account. An example for this is deleteInBatch(…)
of JpaRepository
which is different from delete(…)
as it uses a query to delete the given entities which is more performant but comes with the side effect of not triggering the JPA-defined cascades (as the spec defines it).
We generally recommend not to use these base interfaces as they expose the underlying persistence technology to the clients and thus tighten the coupling between them and the repository. Plus, you get a bit away from the original definition of a repository which is basically “a collection of entities”. So if you can, stay with PagingAndSortingRepository
.
Custom repository base interfaces
The downside of directly depending on one of the provided base interfaces is two-fold. Both of them might be considered as theoretical but I think they’re important to be aware of:
- Depending on a Spring Data repository interface couples your repository interface to the library. I don’t think this is a particular issue as you’ll probably use abstractions like
Page
orPageable
in your code anyway. Spring Data is not any different from any other general purpose library like commons-lang or Guava. As long as it provides reasonable benefit, it’s just fine. - By extending e.g.
CrudRepository
, you expose a complete set of persistence method at once. This is probably fine in most circumstances as well but you might run into situations where you’d like to gain more fine-grained control over the methods expose, e.g. to create aReadOnlyRepository
that doesn’t include thesave(…)
anddelete(…)
methods ofCrudRepository
.
The solution to both of these downsides is to craft your own base repository interface or even a set of them. In a lot of applications I have seen something like this:
interface ApplicationRepository<T> extends PagingAndSortingRepository<T, Long> { }
interface ReadOnlyRepository<T> extends Repository<T, Long> {
// Al finder methods go here
}
The first repository interface is some general purpose base interface that actually only fixes point 1 but also ties the ID type to be Long
for consistency. The second interface usually has all the find…(…)
methods copied from CrudRepository
and PagingAndSortingRepository
but does not expose the manipulating ones. Read more on that approach in the reference documentation.
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 uRead more
We’ll here focus on some minor differences among them.
Differences between @Component, @Repository, @Controller and @Service
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: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@Component
s. If we define our own custom annotation and annotate it with@Component
, it will also get scanned with<context:component-scan>
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 withPersistenceExceptionTranslationPostProcessor
, that we are required to add in our Spring’s application context like this: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.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
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.
Similar to above, in the future Spring may add special functionalities for
See less@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.