2009-11-28 13 views

Respuesta

7

Tendría que darles una referencia a ApplicationContext o BeanFactory para que puedan obtener los beans gestionados por Spring.

+1

¿Cuál es la mejor práctica para hacer esto en una aplicación web? ¿Es común que los objetos de dominio creados dinámicamente necesiten acceso a los beans Spring de esta manera? –

+1

Recomiendo consultar WebApplicationContextUtils: http://static.springsource.org/spring/docs/3.0.0.RC1/javadoc-api/. Creo que es más común dejar que Spring administre los beans. Solo los beans locales dentro de un contexto de llamada de método se crearían usando "nuevo". – duffymo

0

Puede utilizar el enfoque que @duffymo sugirió, pero en el caso de que no esté ejecutando Spring como una aplicación web debe mirar este SO entry. Verifique que la clase de utilidad esté protegida contra subprocesos en la respuesta más popular. Por el OP y la respuesta debe obtener todo lo que necesita y luego puede usar esta clase de utilidad para obtener una referencia a los beans gestionados de Spring.

8

@ La respuesta de duffymo es la solución más común a este problema, y ​​la que probablemente deba seguir.

Sin embargo, si se siente descarado, y si su situación lo permite, entonces se podría considerar el uso de apoyo AspectJ de primavera a autowire your non-spring-managed domain objects con granos de primavera:

[...] contiene una anotación impulsada aspecto que explota esta capacidad para permitir la inyección de dependencia de cualquier objeto . El soporte está destinado a ser utilizado para objetos creados fuera de el control de cualquier contenedor. Los objetos de dominio a menudo entran en esta categoría porque a menudo se crean mediante el uso del nuevo operador , o mediante una herramienta ORM como resultado de una consulta de base de datos.

Está llegando al vudú, esto solo funciona en ciertos servidores de aplicaciones, pero podría ser la herramienta para ti.

3

Spring tiene un mecanismo llamado SingletonBeanFactoryLocator que puede usar en lugares, como aplicaciones EJB 2.0, para obtener el contexto de la fábrica/aplicación de frijoles en lugares donde no puede usar la inyección de dependencia. Hay un gancho en el Spring ContextLoader existente que ya está utilizando para aprovechar esta funcionalidad, aunque es algo complicado de configurar.

Tendrá que separar sus contextos de aplicación en una relación padre/hijo. El elemento primario contendrá los objetos de la capa de servicio, mientras que el elemento secundario estará compuesto por elementos específicos de la capa web.

A continuación, tendrá que añadir un par de parámetros de contexto a su web.xml (como se hace para la ubicación de configuración) para indicarle que debe inicializar la matriz:

<context-param> 
    <param-name>locatorFactorySelector</param-name> 
    <param-value>classpath:beanRefFactory.xml</param-value> 
</context-param> 

<context-param> 
    <param-name>parentContextKey</param-name> 
    <param-value>beanRefFactory</param-value> 
</context-param> 

El locatorFactorySelector es una referencia a un archivo xml, PERO (aquí es donde siempre me confundo) esto no va a apuntar al xml que define sus servicios. Es un xml de definición de bean que crea un bean de contexto de aplicación. Que luego referencia este bean usando el atributo parentContextKey.

Por ejemplo, beanRefFactory.xml contendría entonces:

<beans> 
    <bean id="beanRefFactory" 
     class="org.springframework.context.support.ClassPathXmlApplicationContext"> 
     <constructor-arg> 
      <list> 
       <value>service-context.xml</value> 
      </list> 
     </constructor-arg> 
    </bean> 
</beans> 

En sus objetos de dominio no murió, entonces podría llegar al contexto de aplicación con este código:

BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector); 
    BeanFactoryReference contextRef= locator.useBeanFactory(parentContextKey); 
    ApplicatonContext context = (ApplicationContext) contextRef.getFactory(); 

Puede encontrar más información sobre ContextSingletonBeanFactoryLocator en this blog post. También hay una buena descripción del uso de este enfoque en el capítulo sobre EJB en Java Development with the Spring Framework.

0

Una solución es utilizar un método global static que devuelve el concurso de la aplicación de Primavera (ver BeanLocator.)

Otras opciones podrían ser tener sus objetos de negocio implementan la interfaz ApplicationContextAware. En la creación de instancias, su código de "integración" debería inyectar Spring ApplicationContext en el bean creado dinámicamente (tal vez verificando si la clase implementa ApplicationContextAware). Esto, por supuesto, vincularía su código comercial con Spring, pero la primera opción sería la misma .

Una variación sería no inyectar directamente el ApplicationContext pero reutilizar la anotación Spring @Autowired. El código de "integración" luego inyectaría solo los campos anotados.

3

Crear una fábrica y registrarlo con la primavera, utilizar la fábrica para crear el objeto de dominio en lugar de utilizar 'nuevo'

en este caso, tiene todos los extras disponibles para su DomainObjFactory

1

Ligeramente relacionados question

Puede adoptar una estrategia similar a la de Hibernate, creando instalaciones para los interceptores en la fábrica de instancias de su dominio. Puede inyectar los servicios necesarios en interceptores administrados por resorte, que se inyectan en las fábricas de su dominio

Esto desataría su aplicación de las interfaces específicas de Spring. El ejemplo a continuación podría simplificarse con genéricos, pero debería hacerse una idea.

public interface Interceptor { 
    public void onCreate(Object entity); 
} 

public class DomainFactory { 
    public void setInterceptors(List<Interceptor> interceptors) { ... } 
    public Object createInstance() { 
    // iterate interceptors, call onCreate 
    } 
} 

public interface MyServiceAware { 
    public void setMyService(MyService service); 
} 

public class MyServiceInjector implements Interceptor { 
    private MyService myService; 
    public void onCreate(Object entity) { 
    if (entity instanceof MyServiceAware) 
     ((MyServiceAware) entity).setMyService(myService); 
    } 
} 

allí tendría que configurar algo así como

<bean id="myServiceInjector" class="MyServiceInjector"> 
    <property name="myService" ref="someServiceBean" /> 
</bean> 

<bean class="DomainFactory"> 
    <property name="interceptors"> 
    <list> 
     <ref bean="myServiceInjector"/> 
    </list> 
    </property> 
</bean> 
0

Se podría hacer que el objeto dependiente de un producto único con un método estático getInstance() que podría ser utilizado por la no-primavera logrado los objetos de dominio. A continuación, ponerlo a disposición de la primavera a través de org.springframework.beans.factory.config.MethodInvokingFactoryBean como:

<bean id="myObject" 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="staticMethod"> 
     <value>com.example.MyObject.getInstance</value> 
    </property> 
</bean> 
Cuestiones relacionadas