Context: Web application
I haven't used Spring before, but according to the Spring docs, all the beans are singleton
, unless we declare them as prototype
.
Normally I instantiate new DAO when there is a call to the business/service layer. If it is a RESTfull service, I instantiate almost all the objects which depend on the call.
I can annotate data access classes with @Repository
and also I can use @Service
for service layer classes.
So my classes with above annotations are singleton
by default. There is a @Scope
annotation that we can declare them as prototype, but nobody seems doing this.
new Object();
each timesingleton
My questions are,
@Repository
is singleton
, how does it handle thread safety when there is no such a thing addressed? (Assume it is done by spring proxies)@Repository
is enough or adding @Scope('prototype')
would be better ?@Scope('prototype')
with @Repository
(according to the tutorials, blogs, etc). Is there a well know reason?Thanks
Spring @Repository annotation is used to indicate that the class provides the mechanism for storage, retrieval, search, update and delete operation on objects.
It is indeed not necessary to put the @Repository annotation on interfaces that extend JpaRepository ; Spring recognizes the repositories by the fact that they extend one of the predefined Repository interfaces. From the javadoc: Annotation to enable JPA repositories.
We don't need to use @Repository annotation when we are extending JpaRepository because Spring detects that the predefined JpaRepository has been extended and recognises the interface that extends JpaRepository as a repository.
@Repository Annotation is a specialization of @Component annotation which is used to indicate that the class provides the mechanism for storage, retrieval, update, delete and search operation on objects.
You're correct - in Spring world most of the beans are singletons.
- The way I used before (creating new instance each time) is incorrect ?
It is not incorrect since it works. The problem about it is that you instantiate a new instance of DAO on each request - in some cases it might be expensive, and anyway it doesn't make any sense - why would you need a bunch of DAO instances? Spring on the other hand not only creates a singleton but also injects DAO's to services or other DAO's e.t.c. i.e. does a lot of work for you
- If @Repository is singleton, how does it handle thread safety when there is no such a thing addressed? (Assume it is done by spring proxies)
When you are writing a @Repository bean, you would normally inject there a DataSource or an EntityManager. DataSource.getConnection() method should be thread safe. With regard to EntityManager, Spring will inject a proxy which will behave differently for different threads, i.e. different threads won't share the same JPA session.
- What is the best practice, @Repository is enough or adding @Scope('prototype') would be better ?
The best practice (or rather a most wide-spread approach) is to just use @Repository
- I don't see anyone use @Scope('prototype') with @Repository (according to the tutorials, blogs, etc). Is there a well know reason?
The reason is that there's no profit from creating multiple instances of @Repository beans
- What if my DAO class is accessed by multiple large number of threads with very high frequency? (This is the one I concern the most)
Again here singleton is better than creating a new object for each request. Just avoid redundant synchronization so your threads won't block on some monitor
No, but it's much harder to unit test, which is what dependency injection is all about. By injecting a DAO in a service, you can easily unit-test the service by injecting a mock DAO during the test. That's not possible if the service creates its own DAO.
A repository is typically completely stateless except for a thread-safe entity manager, session factory or JDBC template initialized at startup time, so being called concurrently is not a problem: it's thread-safe.
There's no reason for a repository to be a prototype. Injecting a prototype DAO into a singleton service will still cause each prototype to be called concurrently anyway.
There's no reason to do it.
No problem: it should be thread-safe if coded correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With