2010-05-18 8 views
6

que tiene un conjunto unitario que tiene un resorte inyectada Dao (simplificado abajo):inyección de dependencia en su Singleton

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); 
    } 
} 

Mi config primavera, probablemente se verá así:

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

Pero esto va a crear una instancia MyService durante el inicio.

¿Hay una forma programática de hacer una inyección de dependencia de MyDao en MyService, pero no tener la primavera para administrar el MyService?

Básicamente quiero ser capaz de hacer esto desde mi código:

MyService.getInstance().doSomething(); 

al tiempo que la primavera inyectar el MyDao para mí.

Respuesta

2

Si desea un singleton, ¿por qué no simplemente define esa clase en las configuraciones de Spring, y es automáticamente un singleton (por defecto).

Para evitar la inicialización en el arranque, ¿ha mirado a Spring lazy initialisation? Básicamente necesita:

lazy-init="true" 

en su definición de bean.

+0

¿Y tienes que obtener el bean usando ApplicationContext donde lo necesites? – Langali

+0

Me gustaría * normalmente * obtener mi frijol de nivel superior en la inicialización y luego hacer referencia a otros frijoles según sea necesario de ese grano de nivel superior. Pero podrías hacer lo que estás sugiriendo. –

0

como han mencionado otros, que debe dejar que la primavera administrar sus únicos, pero si desea administrar por sí mismo y dejar que la primavera inyectar dependencias, hacer esto:

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

creo que la interfaz FactoryBean es una buena alternativa para ti Es una muy buena opción cuando necesita ejecutar alguna lógica de inicialización. Por ejemplo, para iniciar una base de datos en memoria o algunos procesos en segundo plano en hilos separados.

Puede leer más al respecto en el reference documentation.

Un ejemplo que demuestra cómo instanciar una base de datos y devolver un origen de datos cada vez que alguien quiere un bean de la implementación de FactoryBean.

@PostConstruct 
void init() { 
    embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath) 
     .addScript(dataPath).setType(embeddedDatabaseType).build(); 
} 


public DataSource getObject() throws Exception { 
    return embeddedDatabase; 
} 

Esto permite el acoplamiento flojo entre la lógica de fábrica y el objeto devuelto. Es muy utilizado por el marco de Spring internamente.

Si desea que se inicialice la primera vez que lo usa, establezca la inicialización diferida en verdadero.

Otra alternativa si desea que su código interactúe con el contenedor Spring es crear una fábrica que implemente la interfaz ApplicationContextAware.A continuación, puede hacer algo como esto:

myDao = context.getBean(MyDao.class); 
4

Aquí es una solución, crear una clase con un método de fábrica estática:

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(); 
    } 
} 

y el uso de primavera para initilize que:

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

y ahora usted debería ser capaz de hacer:

MyService.getInstance().doSomething(); 

sin ningún problema.

Cuestiones relacionadas