Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection into your Singleton

I have a singleton that has a spring injected Dao (simplified below):

public class MyService<T> implements Service<T> {
    private final Map<String, T> objects;
    private static MyService instance;

    MyDao myDao;

    public void set MyDao(MyDao myDao) {
        this. myDao = myDao;
    }

    private MyService() {
        this.objects = Collections.synchronizedMap(new HashMap<String, T>());
        // start a background thread that runs for ever
    }

    public static synchronized MyService getInstance() {
        if(instance == null) {
            instance = new MyService();
        }
        return instance;
    }

    public void doSomething() {
        myDao.persist(objects);
    }
}

My spring config will probably look like this:

 <bean id="service" class="MyService" factory-method="getInstance"/>

But this will instantiate the MyService during startup.

Is there a programmatic way to do a dependency injection of MyDao into MyService, but not have spring manage the MyService?

Basically I want to be able to do this from my code:

MyService.getInstance().doSomething();

while having spring inject the MyDao for me.

like image 935
Langali Avatar asked May 18 '10 20:05

Langali


People also ask

Is dependency injection a singleton pattern?

The Singleton design pattern ensures an object only has once instance and cannot be re-instantiated. For Dependency Injection, typically you would create an instance of the service outside of the target object (the client) and pass it to the client.

Can you inject transient into singleton?

Transient services that are stateless and don't contain any stateful dependencies can be injected into singleton or scoped services. A transient service injected into a singleton has singleton lifetime, it's not disposed until the app shuts down.

Why should you avoid singletons?

The most important drawback of the singleton pattern is sacrificing transparency for convenience. Consider the earlier example. Over time, you lose track of the objects that access the user object and, more importantly, the objects that modify its properties.

What is singleton injection?

Singleton is a design pattern, It means that there will be a single copy of your object inside server memory, which will be shared among all the requests (http/client). So, when you register any dependency in your application as a Singleton, then you will get a single copy of an object per server/node/instance.


2 Answers

Here is a solution, create a class with a static factory method:

public class MyService {
    private static MyService instance;

    private MyDao myDao;

    public static MyService createInstance(final MyDao myDao) {
      instance = new MyService(myDao);
      return instance;
    }

    private MyService(final MyDao myDao) {
      this.myDao = myDao;
    }

    public static synchronized MyService getInstance() {
      return instance;
    }

    public void doSomething() {
      // just do it!
      myDao.justDoIt();
    }
}

and use spring to initilize it:

  <bean class="my.path.MyService" factory-method="createInstance" scope="singleton">
    <constructor-arg ref="reference.to.myDao" />
  </bean>

and now you should be able to do:

MyService.getInstance().doSomething();

without any problems.

like image 190
Chango Avatar answered Sep 24 '22 10:09

Chango


If you want a singleton, why not just define that one class in the Spring configs, and it's automatically a singleton (by default).

To avoid initialising at start up, have you looked at Spring lazy initialisation ? Basically you need:

lazy-init="true"

in your bean definition.

like image 20
Brian Agnew Avatar answered Sep 20 '22 10:09

Brian Agnew