Dependency Injection Into Your Singleton

I have a singleton that has spring introduced by Tao (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 configurator will probably look like this:

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

But this will create an instance of MyService at startup.

Is there a programmatic way to inject MyDao dependencies into MyService but not have spring manage MyService?

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

 MyService.getInstance().doSomething(); 

having spring for entering MyDao for me.

+6
spring dependency-injection singleton
source share
4 answers

Here is the 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 initialize it:

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

and now you can do it:

 MyService.getInstance().doSomething(); 

no problem.

+4
source share

If you need a singleton, why not just define one class in Spring configurations, and it will automatically be a single (by default).

To avoid initialization at startup, did you consider Spring lazy initialization ? Basically you need:

 lazy-init="true" 

in the definition of bean.

+2
source share

As others have already mentioned, you must let spring manage your singleons, but if you want to manage them yourself and just let spring set dependencies, do the following:

 applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService); 
0
source share

I believe the FactoryBean interface is a good alternative for you. This is a very good choice when you need to execute some initialization logic. For example, to run a database in memory or some background processes in separate threads.

You can read more about this in the reference documentation .

An example that demonstrates how I create a database and return a data source every time someone wants a bean from a FactoryBean implementation.

 @PostConstruct void init() { embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath) .addScript(dataPath).setType(embeddedDatabaseType).build(); } public DataSource getObject() throws Exception { return embeddedDatabase; } 

This provides a loose connection between the factory logic and the returned object. It is widely used by Spring framework inside.

If you want it to be initialized the first time you use it, set lazy-initialization to true.

Another option if you want your code to interact with the Spring container is to create a factory that implements the ApplicationContextAware interface. Then you can do something like this:

 myDao = context.getBean(MyDao.class); 
0
source share

All Articles