1. Prefacio
En proyectos anteriores, rara vez presté atención a la implementación específica y la teoría de la AOP de primavera. Entendí brevemente qué es AOP y cómo usarlo. Vi una publicación de blog que estaba bien escrita, así que llegué a aprenderla.
AOP
Se puede decir que AOP (programación orientada al aspecto), es decir, programación orientada a los aspectos, es un suplemento y una mejora de la OOP (programación orientada a objetos). OOP introduce conceptos como encapsulación, herencia y polimorfismo para establecer una jerarquía de objetos que se utiliza para simular una colección de comportamiento público. Sin embargo, OOP permite a los desarrolladores definir relaciones verticales, pero no es adecuada para definir relaciones horizontales, como las funciones de registro. El código de registro a menudo se dispersa horizontalmente en todos los niveles de objeto, y no tiene nada que ver con las funciones centrales del objeto correspondiente. Este tipo de código no relacionado disperso en todas partes se llama Cross Cutting. En el diseño de OOP, causa una gran cantidad de duplicación de código, que no es propicio para la reutilización de cada módulo.
La tecnología de AOP, por el contrario, utiliza una técnica llamada "corte transversal" para diseccionar el interior de un objeto encapsulado y encapsular esos comportamientos comunes que afectan múltiples clases en un módulo reutilizable y nombrarlo "aspecto", que es la faceta. La llamada "sección" está simplemente encapsulada por la lógica o las responsabilidades que no están relacionadas con el negocio, pero que el módulo comercial lo llama conjuntamente, lo que es conveniente para reducir el código duplicado del sistema, reduciendo el acoplamiento entre los módulos y que conducen a la operación y la mantenimiento futuras.
Utilizando la tecnología "transversal", AOP divide el sistema de software en dos partes: preocupación central y preocupación transversal. El principal proceso de procesamiento comercial es el enfoque central, y la parte que tiene poco que ver con él es el enfoque transversal. Una característica de las preocupaciones transversales es que a menudo ocurren en múltiples preocupaciones básicas, y son básicamente similares en varios lugares, como la autenticación de permisos, los registros y las cosas. El papel de AOP es separar diversas preocupaciones en el sistema y separar las preocupaciones centrales de las preocupaciones transversales.
Concepto de núcleo de AOP
1. Puntos de atención cruzados
¿Qué métodos interceptar y cómo lidiar con él después de la intercepción? Estas preocupaciones se llaman preocupaciones transversales
2. Sección (aspecto)
Las clases son abstracciones de las características de los objetos, y las secciones son abstracciones de preocupaciones transversales
3. Unión de unión
El punto interceptado, porque Spring solo admite puntos de conexión de tipo método, por lo que el punto de conexión en Spring se refiere al método interceptado. De hecho, el punto de conexión también puede ser un campo o un constructor.
4. Pointcut
Definición de puntos de conexión de interceptación
5. Notificación (consejo)
La llamada notificación se refiere al código que se ejecutará después de interceptar el punto de conexión. Las notificaciones se dividen en cinco categorías: notificaciones preestablecidas, postset, excepción, final y circundantes.
6. Objeto objetivo
El objeto objetivo del proxy
7. tejido
El proceso de aplicar una hendidura a un objeto objetivo y causar la creación de objetos proxy
8. Introducción
Sin modificar el código, la introducción puede agregar dinámicamente algunos métodos o campos a la clase durante el período de ejecución
Soporte de primavera para AOP
El agente AOP en Spring es responsable de la generación y la gestión del contenedor del COI de Spring, y sus dependencias también son administradas por el contenedor IOC. Por lo tanto, el proxy AOP puede dirigirse directamente a otras instancias de frijoles en el contenedor, y esta relación se puede proporcionar mediante la inyección de dependencia del contenedor del COI. Las reglas para crear un proxy en primavera son:
1. Por defecto, Java Dynamic Proxy se usa para crear AOP proxy, para que pueda crear proxy para cualquier instancia de interfaz.
2. Cuando la clase que necesita un proxy no es una interfaz proxy, Spring cambiará a usar proxy CGLIB, y también puede obligar a CGLIB a usar.
La programación de AOP es en realidad algo muy simple. Mirando la programación de AOP, los programadores solo necesitan participar en tres partes:
1. Definir componentes comerciales ordinarios
2. Defina el punto de entrada, un punto de entrada puede cortar múltiples componentes comerciales
3. Defina el procesamiento mejorado. El procesamiento mejorado es la acción de procesamiento que se teje en componentes comerciales ordinarios en el marco AOP.
Por lo tanto, la clave para la programación de AOP es definir el punto de entrada y definir el procesamiento de mejora. Una vez que se definen el punto de entrada y el procesamiento de mejora apropiados, el marco AOP generará automáticamente un proxy AOP, es decir, el método de objeto proxy = procesamiento de mejora + método de objeto proxy.
Aquí hay una plantilla de archivo .xml Spring AOP llamada AOP.XML, y el contenido posterior se expande en AOP.xml:
<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: tx = "http://www.springframework.org/schema/tx" xsi: schemalocation http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/ http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> </beans>
Implementación simple de AOP basada en la primavera
Tenga en cuenta que antes de explicar, permítanme explicar: para ejecutar con éxito el código, no es suficiente usar el paquete JAR proporcionado por Spring al desarrollador. Descargue dos paquetes jar en línea:
1. AOPALIANCE.JAR
2. AspectJweaver.jar
Comencemos a explicar el método de implementación XML de Spring AOP, primero definir una interfaz:
interfaz pública Helloworld {Void Printhelloworld (); void doprint ();} Definir dos clases de implementación de interfaz:
clase pública HELLOWORLDIMPL1 implementa HelloWorld {public void PrinthellowOrld () {System.out.println ("Ingrese a HelloWorldImpl1.printhelloworld ()"); } public void doprint () {System.out.println ("Ingrese HelloworldImpl1.doPrint ()"); devolver ; }} clase pública HELLOWORLDIMPL2 Implementa HelloWorld {public void Printhelloworld () {System.out.println ("Ingrese a HelloWorldImpl2.printhelloworld ()"); } public void doprint () {System.out.println ("Enter HelloWorldImpl2.Doprint ()"); devolver ; }} Enfoque transversal, aquí está el tiempo de impresión:
public class TimeHandler {public void printtime () {System.out.println ("currenttime =" + system.currentTimemillis ()); }} Con estas tres clases, puede implementar un Spring AOP simple. Eche un vistazo a la configuración de aop.xml:
<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: tx = "http://www.springframework.org/schema/tx" xsi: schemalocation http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/ http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <bean id =" helloworldImpl1 "/> <bean id =" helloworldIml2 "/> <bean id =" timeHandler "/> <aop: config> <aop: aspecto id =" tiempo "reh =" a tiempo "<a auasta" <auasta " id = "addallMethod" Expression = "Ejecution (* com.xrq.aop.helloworld.* (..))" /> <aop: antes del método = "printtime" point-ref = "addallmethod" /> <aop: después del método = "imprenttime" pointcut-ref = "addallmethod" /> </aop: asco> < /aop: configuración> < /beatm.
Escriba una función principal para llamarlo:
public static void main (string [] args) {applicationContext ctx = new ClassPathXMLApPlicationContext ("aop.xml"); HelloWorld hw1 = (helloworld) ctx.getBean ("helloworldimpl1"); HelloWorld hw2 = (HelloWorld) ctx.getBean ("helloworldimpl2"); hw1.printhelloworld (); System.out.println (); HW1.DOPRINT (); System.out.println (); System.out.println (); hw2.printhelloworld (); System.out.println (); hw2.doPrint ();} El resultado de la ejecución es:
CurrentTime = 14461296119993enter helloworldimpl1.printhelloworld () currenttime = 1446129611993currenttime = 1446129611994enter helloworlldimpl1.doPrint () CurrentTime = 1446129611994CurrentTime = 14461296111111111111194enter Helloworldimpl2.printhelloworld () CurrentTime = 1446129611994CurrentTime = 1446129611994Ener Helloworldimpl2.doPrint () CurrentTime = 1446129611994
Vi que todos los métodos de las dos clases de implementación de la interfaz Helloworld se han agregado al proxy, y el contenido de proxy es el tiempo de impresión.
Detalles adicionales sobre el uso de AOP basado en primavera
1. Agregue una preocupación transversal e imprima el registro. La clase Java es:
public class logHandler {public void logbefore () {system.out.println ("log antes del método"); } public void logafter () {System.out.println ("Método de registro después"); }}<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: tx = "http://www.springframework.org/schema/tx" xsi: schemalocation http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/ http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <bean id =" helloworldImpl1 "/> <bean id =" helloworldIml2 "/> <bean id =" timeHandler "/> <bean id =" loghandler "/> <aop: config> <aop: aspecto de aspecto" id = "time" afirner " orden = "1"> <aop: pointCut id = "addtime" expresion = "ejecution (* com.xrq.aop.helloworld.* (..))" /> <aop: antes del método = "printtime" point-ref = "addtime" /> <aop: después del método = "imprenttime" point-ref = "addtime" /> < /aop: aspecto> <aop: aspecto Idm. ref = "logHandler" order = "2"> <aop: pointCut id = "printLog" expresion = "ejecution (* com.xrq.aop.helloworld.* (..))" /> <aop: antes del método = "logbefore" point-ref = "printlog" /> <aop: después del método = "logafut" pointcut-ref = "printLog" /augs: además: además: además: además: además: APOP: APO </aop: config> </le beans>
La clase de prueba permanece sin cambios, y el resultado de la impresión es:
CurrentTime = 1446130273734log antes del metodenter helloworldImpl1.printhelloworld () log después de métodoscurrentTime = 1446130273735CurrentTime = 14461302737336Log antes del metodenter hellowOrldImpl1.doPrint () log después de métodos = 1446113027373737376CURNTIMETIME = 1446130273736Log antes del metodenter helloworldimpl2.printhelloworld () log después de metodCurrentTime = 1446130273736CurrentTime = 14461302737337Log antes del metodénter hellowOrldImppl2.doPrint () log después del método CurrentTime = 144613027373377377 antes del metodenter
Hay dos formas de usar LogHandler antes del TimeHandler:
(1) Hay un atributo de orden en el aspecto, y el número del atributo de pedido es el orden de cortar los puntos de enfoque
(2) Defina el LogHandler antes del TimeHandler. Spring utiliza el orden de definición de aspecto como orden de tejido de forma predeterminada.
2. Solo quiero tejer algunos métodos en la interfaz
Simplemente modifique la expresión de PointCut:
<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: tx = "http://www.springframework.org/schema/tx" xsi: schemalocation http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/ http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <bean id =" helloworldImpl1 "/> <bean id =" helloworldIml2 "/> <bean id =" timeHandler "/> <bean id =" logHandler "/> <aop: config> <aop: aspecto de aspecto id =" Time "REHHANTER" REF. Order = "1"> <aop: PointCut id = "Addtime" Expression = "Execution (* com.xrq.aop.helloworld.print* (..))" /> <aop: antes del método = "printtime" point-ref = "addtime" /> <aop: después del método = "improntime" point-ref = "addtime" /> < /aop: aspecto> <aop: apariencia: apariencia = "log" ref = "logHandler" order = "2"> <aop: pointCut id = "printLog" expresion = "ejecution (* com.xrq.aop.helloworld.do* (..))" /> <aop: antes del método = "logBeFore" Point-ref = "printLog" /> <aop: después del método = "logafter" punto-rehef = "printLog" /aop: </aop: config> </le beans>
Significa que TimeHandler solo tejerá métodos que comienzan al comienzo de la impresión de la interfaz de Helloworld, LogHandler solo tejerá métodos que comienzan al comienzo de la interfaz de Helloworld.
3. Forzar a CGLIB a generar proxy
Como se mencionó anteriormente, Spring utiliza proxy dinámico o CGLIB para generar proxy. Las versiones más altas de Spring elegirán automáticamente si usar proxy dinámico o CGLIB para generar contenido proxy. Por supuesto, también podemos obligar a CGLIB a generar proxy, es decir, hay un atributo de "clase proxy-target" en <aop: config>. Si este valor de atributo se establece en True, entonces el proxy basado en la clase funcionará. Si el proxy-Target-Class se establece en falso o se omite este atributo, entonces el proxy basado en la interfaz funcionará.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.