Tenemos algunos objetos de dominio creados en tiempo de ejecución, no en Spring. Estos objetos de dominio necesitan acceso a algunos beans de tipo de servicio que Spring administra. ¿Cómo pueden los objetos de dominio que se crean en tiempo de ejecución acceder a Spring beans dinámicamente (no por DI)?Acceso a Spring bean * not * mediante la inyección de dependencia
Respuesta
Tendría que darles una referencia a ApplicationContext o BeanFactory para que puedan obtener los beans gestionados por Spring.
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.
@ 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.
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.
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.
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
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>
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>
- 1. Logging Spring Bean creación/inyección de dependencia
- 2. Inyección de Dependencia con Spring/Junit/JPA
- 3. JAR mínimos para la inyección de dependencia Spring 3.0
- 4. ¿Cómo funciona la inyección de dependencia en Spring?
- 5. inyección de Spring Bean en un método principal clase
- 6. Inyección de dependencia de tiempo de ejecución con Spring
- 7. ¿Inyección de dependencia mediante constructores o definidores de propiedad?
- 8. Inyección condicional de bean
- 9. Dependencia Inyección a los módulos
- 10. Spring @Async Not Working
- 11. Inyección de dependencia en MVC
- 12. Cómo XML configura Spring Bean para inyección de constructor cuando bean tiene varargs constructor
- 13. Inyección de dependencia con el archivo ".properties"
- 14. Inyección de Dependencia wcf
- 15. La inyección de dependencia y la fábrica
- 16. ¿Cómo aplico la inyección de dependencia a una fábrica abstracta
- 17. Inyectando el Inyector de Dependencia usando la Inyección de Dependencia
- 18. ¿Por qué Spring no admite la inyección directa de dependencia de campo (excepto para autocableado)?
- 19. ¿La inyección de dependencia de Spring no rompe la ocultación de información?
- 20. Spring (MVC) ¿Evita la inyección de SQL?
- 21. ¿Cuándo usa la inyección de dependencia?
- 22. inyección de prueba Spring + Mockito
- 23. alternativas de inyección de dependencia
- 24. JSF-bean gestionado EJB inyección
- 25. ¿Qué es la Inyección de Dependencia?
- 26. Usa correctamente la inyección de dependencia
- 27. La inyección de dependencia con múltiples repositorios
- 28. Uso de la inyección de dependencia en una biblioteca
- 29. Inyección de dependencia con Jersey
- 30. Inyección de dependencia sin marco
¿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? –
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