2011-11-14 7 views
6

Tengo un ServiceA que tiene una dependencia en ServiceB. El servicioB proviene de un archivo de Spring Bean con lazy-init = true, es decir, solo quiero que el servicio B se inicialice cuando solicite ese bean.Spring DI - no inicialice todos los beans dependientes

Sin embargo, sí uso ServiceA en toda mi aplicación y cuando hacemos una inyección basada en setter ServiceB se inicializa.

Quiero ServiceA para no inicializar ServiceB hasta se llama a cualquier método en ServiceA que necesite ServiceB. Una forma de hacerlo fue usando los Aspectos , pero estaba buscando la solución más simple posible para esto particularmente en el archivo xml de primavera para serviceB o alguna anotación en serviceB o cualquier indicador de proxy.

¿Alguien puede ayudar?

+0

posible duplicado de [¿Hay una fábrica de proxy lazy spring en Spring?] (Http://stackoverflow.com/questions/2391168/is-there-a-spring-lazy-proxy-factory-in-spring) – skaffman

+0

¿Qué tal pasar una fábrica de ServiceB a ServiceA? –

Respuesta

6

Creo que LazyInitTargetSource hace lo que necesita.

útil cuando se necesita una referencia proxy en la inicialización pero el objeto de destino real no debe ser inicializado hasta el primer uso. Cuando el bean de destino se define en un ApplicationContext (o un BeanFactory que preinstanta con entusiasmo beans de singleton) también debe marcarse como "lazy-init", de lo contrario será instanciado por dicho ApplicationContext (o BeanFactory) al inicio.

0

No sé de Spring, pero en Guice usarías un Provider<ServiceB>, de modo que cuando estuvieras listo para usar el servicio irías al provider.get().callMethodOnB(...).

Esto es, creo, parte de la especificación JSR-330, por lo que es posible que haya algo equivalente en Spring (no he usado una versión actualizada de Spring desde hace bastante tiempo).

+1

¡Ver ahora! Si va a downvote, ¿no sería cortés dejar una nota que diga por qué? – dty

0

También puede usar method injection. Como regla, es necesario obtener una nueva instancia de un bean singleton de un contexto, pero también se puede usar en su caso.

muestra:

package org.test.lazy; 

public abstract class ParentBean { 
    public abstract LazyBean getLazy(); 
    public void lazyDoingSomething() { 
     getLazy().doSomething(); 
    } 
} 

package org.test.lazy; 

public class LazyBean { 
    public void init() { 
     System.out.println("Initialized"); 
    } 
    public void doSomething() { 
     System.out.println("Doing something"); 
    } 
} 

package org.test.lazy; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@ContextConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
public class LazyTest { 

    @Autowired 
    private ParentBean parentBean; 

    @Test 
    public void test() { 
     parentBean.lazyDoingSomething(); 
     parentBean.lazyDoingSomething(); 
    } 
} 

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
"> 
    <import resource="classpath:org/test/lazy/Lazy-context.xml"/> 
    <bean id="parentBean" class="org.test.lazy.ParentBean"> 
     <lookup-method bean="lazyBean" name="getLazy"/> 
    </bean> 
</beans> 

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
" 
default-lazy-init="true"> 

    <bean id="lazyBean" class="org.test.lazy.LazyBean" init-method="init" /> 
</beans> 

Por lo tanto, el bean perezoso se inicializará solo una vez a pedido.

1

Otro enfoque que es posible que desee probar es discutido en http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html:

[LazyInitTargetSourceCreator es una] TargetSourceCreator que hace cumplir una LazyInitTargetSource para cada bean que se define como "flojo-init". Esto conducirá a un proxy creado para cada uno de esos beans, lo que permite obtener una referencia a dicho bean sin inicializar realmente la instancia de bean de destino.

Para ser registrado como TargetSourceCreator personalizada para un creador de proxy automático, en combinación con los interceptores personalizados para los granos específicos o para la creación de sólo sustitutos perezoso-init. Por ejemplo, como autodetectada grano de la infraestructura en un definición del contexto de aplicación XML:

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
    <property name="customTargetSourceCreators"> 
    <list> 
     <bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator"/> 
    </list> 
    </property> 
</bean> 

<bean id="myLazyInitBean" class="mypackage.MyBeanClass" lazy-init="true"> 
    ... 
</bean> 

Si usted se encuentra haciendo esto varias veces en un contexto de aplicación, esto ahorrará de la configuración.

Cuestiones relacionadas