Este artículo trata sobre un problema difícil en Java. Mediante el uso de la biblioteca Core Java para implementar métodos AOP simples y analizar y comparar el código de instancia. Lo siguiente es todo contenido:
Spring es un marco de código abierto muy popular, y AOP (programación seccional) es uno de los conceptos más importantes de la primavera. Para comprender mejor y aprender las ideas de AOP, usar la biblioteca central para lograrla a la vez es una buena manera.
Primero, presentemos el concepto de AOP. AOP (programación orientada al aspecto), es decir, programación orientada a tangencial. La llamada programación orientada tangencial es la idea de diseñar código desde la perspectiva de un área transversal. La idea tradicional de OOP es utilizar la herencia de encapsulación y el polimorfismo para construir una relación jerárquica vertical, pero no es adecuado para definir las relaciones horizontales. La idea de AOP proporciona un buen suplemento a esto.
Por ejemplo, el código de administración de registros a menudo se dispersa horizontalmente en muchos niveles de objetos, pero no tiene nada que ver con las funciones centrales de los objetos correspondientes. También hay muchos códigos similares, como verificación de permisos, salida de depuración, procesamiento de transacciones, etc., que también son los mismos. Esto no es propicio para la reutilización y la gestión de códigos.
En este momento, la tecnología AOP surgió. Utiliza la tecnología de "corte transversal" para penetrar profundamente en el objeto de encapsulación, encapsular los comportamientos comunes que afectan múltiples clases en un módulo reutilizable y nombrarlo "aspecto", es decir, el corte. 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 de negocio llaman 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 posterior.
Entonces, ¿cómo se implementa AOP?
La respuesta es proxy dinámico (habrá otro capítulo sobre el proxy para más detalles, por lo que no entraré en detalles aquí). Hay dos formas de implementar proxy dinámico, uno es el proxy dinámico JDK y el otro es el proxy dinámico CGLIB.
Luego use dos métodos para hacer una castaña simple.
Diseñemos primero un escenario, supongamos que tenemos una interfaz de computación icalculator y una clase de calculadora calculadoraIMPL que implementa esta interfaz.
interfaz pública icalculator {// Operación de adición public int add (int a, int b); // SERTRACTION Public Int Sesto (int a, int b); // múltiples públicos int multiply (int a, int b); // dividencia pública int define (int a, int b);} Public Class CalculatorImpl implementa icalCulator {@Override public int add (int a, int b) {return a + b; } @Override public intstract (int a, int b) {return a - b; } @Override public int multiply (int a, int b) {return a * b; } @Override public int Define (int a, int b) {return a / b; }}¿Cómo registrar el número total de veces que se usa el método de la calculadora sin cambiar el código interno de la clase de calculadora original?
Con proxy dinámico, en realidad es muy simple. Primero cree una clase e implementa la interfaz Invocathandler, anule el método de Invoke.
Public Class TestHandler implementa InvocationHandler {Private Object TargetObject; privado int usetimes; // Atrae el objeto Delegate y devuelva el enlace de objeto público de la clase Proxy (objeto TargetObject) {this.TarGetObject = TargetObject; return proxy.newproxyInstance (TargetObject.getClass (). GetClassLoader (), TargetObject.getClass (). GetInterfaces (), esto); } @Override public Object Invoke (Proxy de objeto, método Método, objeto [] args) lanza lando {// hacer algo antes (); Resultado del objeto = método.invoke (TargetObject, args); después(); resultado de retorno; } private void antes () {System.out.println ("Podemos hacer algo antes de calcular"); } private vacío después () {useTimes ++; System.out.println ("usado:"+usetimes+"times"); }}Aunque parece haber demasiado código, el método principal es el método de Invoke. El resultado del objeto = Method.Invoke (TargetObject, Args); Es equivalente a continuar utilizando los parámetros originales para ejecutar el método original. Las funciones personalizadas anteriores y posteriores son funciones personalizadas, que pueden hacer algunas cosas que queremos hacer antes y después de que se ejecute el código de objeto, como el recuento de uso aquí.
En el método de enlace, el objeto proxy de destino se pasa y se devuelve una instancia de clase proxy. A continuación, veamos cómo usar:
public class testProxy {public static void main (string [] args) {testHandler proxy = new testHandler (); ICALCULTULE calcule = (icalCulator) proxy.bind (nuevo calculatorImpl ()); int resultado = calcular.Add (1,2); System.out.println ("El resultado es:"+resultado); resultado = calcular.subtrato (3,2); System.out.println ("El resultado es:"+resultado); resultado = calculador.multiply (4,6); System.out.println ("El resultado es:"+resultado); resultado = calculador.devide (6,2); System.out.println ("El resultado es:"+resultado); }}Primero definimos un TestHandler y luego obtenemos una instancia de proxy a través del método de enlace, y luego podemos usar esta instancia directamente. Los resultados de la operación son los siguientes:
Podemos hacer algo antes de calcular. Usado: 1 resultado es: 3 Podemos hacer algo antes de calcular. Usado: 2 resultado es: 1 podemos hacer algo antes de calcular. Usado: 3 resultado es: 24 Podemos hacer algo antes de calcular. Usado: 4 resultado es: 3
De esta manera, implementamos la extensión del código sin modificar el código interno de calculatorImpl.
A continuación, use CGLIB para implementarlo una vez.
Primero cree una clase para implementar la interfaz MethodInterceptor y anular el método Intercept. Otros códigos son similares a usar proxy JDK, pero el proceso de obtener objetos proxy es diferente.
clase pública cglibproxy implementa metodinterceptor {private int usetimes; objetivo de objeto privado; Objeto público getInstance (objetivo de objeto) {this.target = target; Potencador potencador = nuevo mejor (); potencer.setsuperClass (this.target.getclass ()); potencador.setCallback (esto); return mejor.create (); } @Override Public Object Intercept (objeto o, método método, objeto [] objetos, métodeProxy MethodProxy) lanza Throwable {antes (); Resultado del objeto = métodeProxy.Invokesuper (o, objetos); después(); resultado de retorno; } private void antes () {System.out.println ("Podemos hacer algo antes de calcular"); } private vacío después () {useTimes ++; System.out.println ("usado:"+usetimes+"times"); }}Pruébalo:
public class testCglibProxy {public static void main (String [] args) {cglibproxy cglibproxy = new cglibproxy (); ICALCULTULE calcule = (icalCulator) cglibproxy.getInstance (nuevo calculatorImpl ()); int resultado = calcular.Add (1,2); System.out.println ("El resultado es:"+resultado); resultado = calcular.subtrato (3,2); System.out.println ("El resultado es:"+resultado); resultado = calcular.multiply (4,6); System.out.println ("El resultado es:"+resultado); resultado = calcular.devide (6,2); System.out.println ("El resultado es:"+resultado); }}Los resultados de la operación son los siguientes:
Podemos hacer algo antes de calcular. Usado: 1 resultado es: 3 Podemos hacer algo antes de calcular. Usado: 2 resultado es: 1 podemos hacer algo antes de calcular. Usado: 3 resultado es: 24 Podemos hacer algo antes de calcular. Usado: 4 resultado es: 3
Ahora obtenemos el mismo resultado. (Se requieren dos paquetes, CGLIB-2.2.2.Jar ASM-3.3.JAR)
Ambos métodos tienen sus propias fortalezas. JDK Proxy necesita configurar una interfaz antes de implementar el proxy. Esta es su desventaja y su ventaja. La desventaja es que esto será un poco más problemático, y no puede presentar a los que ya están encapsulados y no implementa la interfaz. El método de proxy CGLIB no requiere el uso de interfaces. Pero también es por esto que el proxy JDK solo intercepta métodos que sobrescriben las interfaces en la clase, mientras que CGLIB intercepta todas las llamadas de método de la clase. Ambos tienen sus pros y contras, por lo que las circunstancias específicas deben analizarse. En la primavera, se usan dos modos proxy mixtos.