2010-08-21 7 views
6

Cómo podemos inyectar manualmente un objeto sin utilizar la función de contenedores. Hice algo similar a través de la reflexión de la siguiente manera.¿Cómo se implementa manualmente la inyección de dependencia?

Class actionClass = Class.forName("SampleClass"); 
Object actionObject = actionClass.newInstance(); 
Method reqMethod = actionClass.getMethod("setRequest", HttpServletRequest.class); 
reqMethod.invoke(actionObject,request); 

¿Es la manera correcta de hacer DI?

Mi intención es pasar objeto de solicitud a diferentes clases de controlador dinámicamente desde un filtro de despachador, donde obtenemos objetos de solicitud y respuesta. Temo por el rendimiento de la reflexión. ¿Hay algún reemplazo para hacer DI?

Respuesta

0

Dependency Injection implica que se obtienen referencias inicializadas correctamente que aparecen "por arte de magia".

Llama al método setRequest() con el objeto de solicitud, pero DI también permite configurar los campos sin invocar métodos.

Guice no requiere un contenedor, pero utiliza la magia del cargador de clases iniciada en el método principal. ¿Sería eso utilizable para ti?

+0

Me gusta el término "por arte de magia". Cómo está sucediendo la inicialización. Cómo se hace en primavera o en contenedores DI similares. –

+1

La idea es alejar la inicialización tanto de la clase inyectada como de la clase en la que ocurre la inyección, por lo que no saben cómo sucede. Donde mueva el código de inyección a, depende de la implementación, y _you_ esencialmente no necesita saber. Al final, se usa la reflexión, pero eso es como decir que Hibernate está usando JDBC al final. –

+0

Mi intención es pasar el objeto de solicitud a diferentes clases de controlador dinámicamente desde un filtro de despachador, donde obtenemos objetos de solicitud y respuesta. –

5

La inyección de dependencia no es más que proporcionar una clase con sus dependencias, en lugar de tener que encontrarlas por sí mismo (a través de búsquedas únicas/búsquedas, etc.). Para que pueda hacerlo en código trivialmente así:

DatabaseConnection dc = new DatabaseConnection(); 
MyDAO dao = new MyDAO(dc); 

(pseudocódigo). Aquí, el MyDAO se está inyectando con una conexión de base de datos. Si esa conexión de base de datos implementa una interfaz, puede simular esto fácilmente durante la prueba.

2

Bueno, cuando se establece un objeto en otro objeto utilizando el método setter oa través de un constructor, también es la inyección de dependencia. La inyección de dependencia solo significa crear una relación (dependencia) en los objetos.

Usar la reflexión como lo hizo es solo otra forma de hacerlo.

1

¿Por qué usaría la reflexión? ¿Por qué no simplemente:

SampleClass action = new SampleClass(); 
action.setRequest(request); 

Eso hace lo mismo, pero es más fácil de leer, permite al compilador para comprobar que realmente existen los tipos y métodos, te ofrece la Javadoc para el método invocado, permite a su IDE para ayudar en refactorizaciones, ...

Y todavía es inyección de dependencia, porque la acción no busca su solicitud, pero recibe la solicitud durante la inicialización.

Editar: solicitó Thorbjørn Muestro cómo se usaría esa acción. Se inyectaría por sí mismo (usando un setter) en cualquier componente que use la acción. El componente usaría entonces el objeto de acción inyectado.

SampleClass action = new SampleClass(); 
action.setRequest(request); 
Servlet servlet = new ActionBasedServlet(); 
servlet.setAction(action); 

Si servlet está destinado a vivir más que action, es decir, se debe utilizar un nuevo Action cada vez que se necesita uno, se puede inyectar en lugar setter un ActionFactory en servlet.

En este caso concreto, me pregunto si la acción realmente necesita mantener una solicitud como parte de su estado, o puede ser inmutable y simplemente actuar sobre la solicitud aprobada por el Servlet como parámetro de método.En ese caso, la inicialización de tiempo de arranque haría:

SampleClass action = new SampleClass(); 
Servlet servlet = new ActionBasedServlet(); 
servlet.setAction(action); 

y ActionBasedServlet definiría

public void serve(Request req, Response resp) { 
    foo(); 
    action.act(req, resp); 
    bar(); 
} 
+0

La palabra clave 'new' proporciona un enlace extremadamente fuerte de la clase actual a la nueva. La inyección de dependencia _decouples_ esta fuerte unión entre los dos. –

+3

La inyección de dependencia desacopla el componente de sus dependencias. Eso no significa que no debe haber otra parte del código que conozca tanto el componente como su dependencia. SampleClass no está acoplado a la solicitud particular en mi ejemplo. – meriton

+0

En mi caso, el nombre de clase es dinámico. Para hacer una DI común para todas las clases. es decir, por qué utilicé la reflexión. gracias por tu respuesta. –

0

marco de primavera es una de las implementaciones más populares DI. También es de código abierto. Puede consultar la clase org.springframeowrk.beans.BeanUtils, específicamente los métodos copyProperties (todos los 4) para ver ejemplos de cómo hacer esto. Para obtener más información, también puede ver la jerarquía de clases de org.springframework.beans.factory.BeanFactory para diferentes estrategias.

Cuestiones relacionadas