java - ioc - patron de inyeccion
Qué es AOP, Inyección de Dependencia e Inversión de Control en inglés simple (6)
Déjame contarte algunas palabras sobre AOP, espero que sea más fácil de entender. El principio básico de AOP es encontrar tareas / aspectos comunes que retornan en muchos lugares en el código y no pertenecen al negocio de concerete del código. Por ejemplo, escriba para iniciar sesión en cada entrada de cualquier función, o cuando se cree un objeto, envíelo o envíe un correo electrónico al administrador cuando llame a una función específica. Entonces, en lugar de que los programadores se encarguen de este aspecto no empresarial, lo tomamos de ellos y gestionamos estos aspectos más allá de la escena. Que todo lo básico de AOP en 1 pierna ....
Intenté comprender los conceptos relacionados con AOP, Inyección de Dependencia e Inversión de Control SPRING, pero estoy teniendo dificultades para entenderlo.
¿Alguien puede explicar esto en inglés simple?
Entiendo su confusión y me llevó algo de tiempo entender cómo estos conceptos se relacionaron juntos. Así que aquí está mi explicación (de alguna manera personal) de todo esto:
1. Inversión del control
La inversión del control es un principio de diseño bastante genérico que se refiere al desacoplamiento de la especificación de un comportamiento desde el momento en que se ejecuta. Compare por ejemplo,
myDependency.doThis();
con
myDependency.onEventX += doThis();
En este último caso, no hay una invocación directa que sea más flexible. En su forma general, la inversión del control se relaciona con el patrón del observador , eventos o devoluciones de llamada .
2. Inversión de dependencia
La inversión de dependencia es otro principio de diseño. En términos generales, dice que la abstracción de mayor nivel no debe depender directamente de las abstracciones de menor nivel; esto resulta de hecho en un diseño en el que la abstracción de mayor nivel no puede reutilizarse sin las abstracciones de menor nivel.
class MyHighLevelClass {
MyLowLevelClass dep = new MyLowLeverClass();
}
class App {
void main() { new HighLevelClass().doStuff(); }
}
Aquí, MyHighLevelClass
no puede compilar sin acceso a MyLowLevelClass
. Para romper este acoplamiento, necesitamos abstraer la clase de bajo nivel con una interfaz, y eliminar la instanciación directa.
class MyLowLevelClass implements MyUsefulAbstraction { ... }
class MyHighLevelClass {
MyUsefulAbstraction dep;
MyHighLevelClass( MyUsefulAbstraction dep ) {
this.dep = dep;
}
}
class App {
void main() { new HighLevelClass( new LowLevelClass() ).doStuff(); }
}
Tenga en cuenta que no necesita nada especial, como un contenedor para imponer la inversión de dependencia, que es un principio. Una buena lectura es el Principio de Inversión de Dependencia de Tío Bob.
3. Inyección de dependencia
Ahora viene la inyección de dependencia. Para mí dependency injection = IoC + dependency inversion
:
- las dependencias se proporcionan externamente, por lo que aplicamos el principio de inversión de dependencia
- el contenedor establece las dependencias (no nosotros) por lo que hablamos de inversión de control
En el ejemplo que proporcioné anteriormente, la inyección de dependencias se puede hacer si se usa un contenedor para crear instancias de objetos e inyectar automáticamente la dependencia en el constructor (hablamos entonces con frecuencia del contenedor DI):
class App {
void main() { DI.getHighLevelObject().doStuff(); }
}
Tenga en cuenta que hay varias formas de inyecciones . Tenga en cuenta también que, bajo esta perspectiva, la inyección del colocador se puede ver como una forma de devolución de llamada: el contenedor DI crea el objeto y luego devuelve la llamada al colocador. El flujo de control se invierte efectivamente.
4. AOP
Estrictamente hablando, AOP tiene poco que ver con los 3 puntos anteriores. El documento seminal sobre AOP es muy genérico y presenta la idea de entrelazar varias fuentes juntas (posiblemente expresadas en diferentes idiomas) para producir un software en funcionamiento.
No ampliaré más en AOP. Lo que es importante aquí, es que la inyección de dependencia y el AOP sí funcionan bien juntos porque hacen que el tejido sea muy fácil. Si se usa un contenedor de IoC e inyección de dependencia para abstraer la creación de instancias de objetos, el contenedor de IoC se puede usar fácilmente para entretejer los aspectos antes de inyectar las dependencias. Esto requeriría una compilación especial o un ClassLoader
especial.
Espero que esto ayude.
Estos tres conceptos son todos diferentes, pero todos funcionan bien juntos, por lo que las aplicaciones de Spring a menudo hacen uso de todo a la vez. Te daré un ejemplo.
Digamos que tenemos una aplicación web que puede hacer muchas cosas diferentes. Podríamos construir esta aplicación de muchas maneras, pero una forma es crear una clase que esté a cargo de hacer cada una de estas cosas. Necesitamos invocar y crear estas clases desde algún lado. Una opción es tener una gran clase principal que crea uno de cada uno de estos servicios, abre un socket y pasa llamadas a estos servicios a medida que entran. Desafortunadamente, nos hemos ido y creamos una clase de Dios, que tiene mucho demasiada lógica y sabe demasiado sobre cómo funciona todo en nuestro programa. Si cambiamos algo sobre nuestro programa, es probable que tengamos que modificar esta clase.
Además, es difícil de probar. No podemos probar ninguna clase de forma aislada si se ejecuta al crear instancias e invocar las otras clases directamente. Las pruebas unitarias se vuelven mucho, mucho más difíciles de escribir.
Una forma de evitar esto es usar la inversión del control. Decimos "está bien, estas son clases de servicio. ¿Quién las instala? Yo no". Generalmente, cada uno define una interfaz, como LoginService o BillingService. Puede haber más de una implementación de esa interfaz, pero a su aplicación no le importa. Simplemente sabe que puede solicitar cierto tipo de servicio o servicio con un cierto nombre, y le devolverá algo agradable.
La inyección de dependencia nos permite unir todas nuestras pequeñas piezas. Las clases tienen campos accesibles, argumentos de constructor o métodos setter que son referencias a los otros componentes a los que necesitarán acceder. Eso hace que las pruebas unitarias sean mucho más fáciles. Puede crear el objeto bajo prueba, arrojar una dependencia falsa o de trozo, y luego probar que el objeto se comportó correctamente de forma aislada.
Ahora, nuestra aplicación real es un revoltijo complejo de piezas que todos necesitan estar conectados de la misma manera. Hay muchas maneras de lograr esto, incluyendo permitir que la aplicación haga suposiciones ("esta clase quiere un UserService, hay exactamente otra clase de la que estoy a cargo que implementa UserService") o explicando cuidadosamente cómo se conectan en XML. o Java Spring, en su núcleo, es un servicio que se encarga de cablear estas clases juntas.
Ahora llegamos a AOP. Digamos que tenemos todas estas clases que están conectadas entre sí de manera elaborada. Hay algunas preocupaciones transversales que podríamos querer describir de maneras muy genéricas. Por ejemplo, tal vez le gustaría iniciar una transacción de base de datos cada vez que se invoca un servicio, y confirmar esa transacción siempre que el servicio no arroje una excepción. Resulta que Spring se encuentra en una posición única para realizar tal tarea. Spring puede crear clases proxy sobre la marcha que implementen cualquier interfaz que necesiten las clases, y puede envolver a su clase en su proxy. Ahora, la IoC y la inyección de dependencia ciertamente no son necesarias para hacer una programación orientada a aspectos, pero es una manera extremadamente conveniente de lograrlo.
La diferencia entre Inyección de Dependencia e Inversión de Control se explica muy bien en
http://martinfowler.com/articles/dipInTheWild.html
("¿Te refieres a la Inversión de Dependencia, verdad?" Sección)
El resumen:
DI trata de cómo un objeto adquiere una dependencia. Cuando una dependencia se proporciona externamente, entonces el sistema usa DI.
IoC se trata de quién inicia la llamada. Si su código inicia una llamada, no es IoC, si el contenedor / sistema / biblioteca vuelve a llamar al código que usted le proporcionó, es IoC.
La inyección de dependencia se explicó muy bien en Cómo explicar la inyección de dependencia a un niño de 5 años. :
Cuando vaya y saque las cosas del refrigerador, puede causar problemas. Podrías dejar la puerta abierta, podrías obtener algo que mamá o papá no quieren que tengas. Incluso podría estar buscando algo que ni siquiera tenemos o que ha expirado.
Lo que debe hacer es indicar la necesidad, "Necesito algo para beber con el almuerzo", y luego nos aseguraremos de que tenga algo cuando se siente a comer.
AOP - Programación Orientada a Aspectos - básicamente significa que la fuente que escribe se modifica con otro código, basado en reglas ubicadas EN OTRA PARTE. Esto significa que puedes decir "como la primera línea de cada método quiero un ''log.debug (" método de entrada () '') ''en un lugar central y todos y cada uno de los métodos que compiles con esa regla en su lugar tendrán entonces esa línea incluida. El "aspecto" es el nombre de buscar en el código de otras maneras que simplemente desde la primera línea de fuente hasta la última.
La inversión de Control básicamente significa que no tienes una pieza central de código que controle todo (como un interruptor gigante en main ()) pero tiene muchos pedazos de código que se llaman "de alguna manera". El tema se discute en Wikipedia: http://en.wikipedia.org/wiki/Inversion_of_control
Una comparación simple de Spring in Action:
Mientras que DI te ayuda a desacoplar los objetos de tu aplicación, AOP te ayuda a desvincular las preocupaciones transversales de los objetos a los que afectan.