Spring @Repository best practices

19,410

Solution 1

You're correct - in Spring world most of the beans are singletons.

  1. 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

  1. 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.

  1. 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

  1. 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

  1. 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

Solution 2

  1. 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.

  2. 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.

  3. 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.

  4. There's no reason to do it.

  5. No problem: it should be thread-safe if coded correctly.

Solution 3

Spring doesn't handle concurrency problems for you. It doesn't meant to. All it does is letting you controll the number of creating instances so your application could work propertly.

Singleton scope (as obvious) will create only one instance of the given bean and pass it to all dependent objects.

Prototype scope for each dependent object will create its own instance, not shared between other objects.

For DAO objects it's very unlikely that you need multiple instances to communicate with database. So singleton is used mostly always.

Solution 4

Components annotated with @Repository should be singleton, because it will never have multiple/different states throughout its lifetime. Yes the only state it can hold is the connection object , which will be set just once during the creation of the object. And It will contain the logic/method(s) to talk to the data store and each method will take/return the data objects required. So it is not required to have multiple instances of repository.

Share:
19,410
sura2k
Author by

sura2k

Student

Updated on June 03, 2022

Comments

  • sura2k
    sura2k almost 2 years

    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.

    • Without using Spring:

    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.

    • With Spring:

    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.

    • Without Spring : new Object(); each time
    • With Spring: singleton

    My questions are,

    1. The way I used before (creating new instance each time) is incorrect ?
    2. 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)
    3. What is the best practice, @Repository is enough or adding @Scope('prototype') would be better ?
    4. I don't see anyone use @Scope('prototype') with @Repository (according to the tutorials, blogs, etc). Is there a well know reason?
    5. 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)

    Thanks