Este artigo é sobre um problema difícil em Java. Usando a biblioteca Java Core para implementar métodos AOP simples e analisar e comparar o código da instância. O seguinte é todo o conteúdo:
A primavera é uma estrutura de código aberto muito popular e a AOP (programação secional) é um dos conceitos mais importantes da primavera. Para entender e aprender melhor as idéias da AOP, usar a biblioteca principal para alcançá -la de cada vez é uma boa maneira.
Primeiro, vamos apresentar o conceito de AOP. AOP (programação orientada para aspectos), ou seja, programação orientada a tangencial. A chamada programação orientada a tangencial é a idéia de projetar código da perspectiva de uma área transversal. A idéia tradicional da OOP é usar a herança e o polimorfismo de encapsulamento para construir um relacionamento hierárquico vertical, mas não é adequado definir relacionamentos horizontais. A Ideia da AOP fornece um bom suplemento a isso.
Por exemplo, o código de gerenciamento de logs geralmente é disperso horizontalmente em muitos níveis de objetos, mas não tem nada a ver com as funções principais dos objetos correspondentes. Também existem muitos códigos semelhantes, como verificação de permissão, saída de depuração, processamento de transações etc., que também são os mesmos. Isso não é propício à reutilização e gerenciamento de código.
Nesse momento, a tecnologia AOP surgiu. Ele usa a tecnologia de "corte cruzado" para penetrar profundamente no objeto de encapsulamento, encapsula os comportamentos comuns que afetam várias classes em um módulo reutilizável e nomeie -o "aspecto", ou seja, o fatiamento. A chamada "seção" é simplesmente encapsulada por lógica ou responsabilidades que não estão relacionadas aos negócios, mas são chamadas em conjunto pelo módulo de negócios, o que é conveniente para reduzir o código duplicado do sistema, reduzindo o acoplamento entre os módulos e conducente à operabilidade e manutenção subsequente.
Então, como a AOP é implementada?
A resposta é um proxy dinâmico (haverá outro capítulo sobre o proxy para obter detalhes, por isso não entrarei em detalhes aqui). Existem duas maneiras de implementar proxy dinâmico, um é o proxy dinâmico do JDK e o outro é o proxy dinâmico do CGLIB.
Em seguida, use dois métodos para fazer uma castanha simples.
Vamos projetar um cenário primeiro, suponha que tenhamos um interface de computação e um calculador de classe de calculadora que implementa essa interface.
interface pública iCiculator {// Operação adicional public int add (int a, int b); // subtração pública int subtract (int a, int b); // múltiplos públicos Int multiply (int a, int b); // dividação pública int define (int a, int b);} classe pública calculatorImpl implementa o iCiculator {@Override public int add (int a, int b) {return a + b; } @Override public int subtract (int a, int b) {return a - b; } @Override public int multiply (int a, int b) {return a * b; } @Override public int Definy (int a, int b) {return a / b; }}Como registrar o número total de vezes que o método da calculadora é usado sem alterar o código interno da classe de calculadora original?
Com proxy dinâmico, é realmente muito simples. Primeiro, crie uma classe e implemente a interface InvocationHandler, substitua o método Invoke.
classe pública testhandler implementa InvocationHandler {Private Object TargetObject; private int a usina; // Ligue o objeto delegado e retorne a classe Proxy Public Object Bind (objeto TargetObject) {this.TargetObject = TargetObject; return proxy.newproxyInstance (TargetObject.getClass (). getClassLoader (), TargetObject.getClass (). getInterfaces (), este); } @Override Public Object Invoke (proxy do objeto, método do método, objeto [] args) lança arremesso {// faça algo antes (); Resultado do objeto = method.invoke (TargetObject, args); depois(); resultado de retorno; } vazio privado antes () {System.out.println ("Podemos fazer algo antes de calcular."); } private void após () {utetimes ++; System.out.println ("Usado:"+usetimes+"Times"); }}Embora pareça haver um pouco demais de código, o método principal é o método de invocar. O objeto resultado = method.invoke (TargetObject, args); É equivalente a continuar usando os parâmetros originais para executar o método original. As funções personalizadas antes e depois são funções personalizadas, que podem fazer algumas coisas que queremos fazer antes e depois que o código do objeto é executado, como o uso da contagem aqui.
No método de ligação, o objeto de proxy de destino é passado e uma instância da classe proxy é retornada. Em seguida, vamos ver como usar:
classe pública testProxy {public static void main (string [] args) {testHandler proxy = new testHandler (); ICICULator calcular = (iCulator) proxy.bind (new CalculatorImpl ()); int resultado = calcular.add (1,2); System.out.println ("O resultado é:"+resultado); resultado = calcular.subtract (3,2); System.out.println ("O resultado é:"+resultado); resultado = calculater.Multiply (4,6); System.out.println ("O resultado é:"+resultado); resultado = calculater.Devide (6,2); System.out.println ("O resultado é:"+resultado); }}Primeiro, definimos um TestHandler e, em seguida, obtemos uma instância de proxy através do método Bind e, em seguida, podemos usar essa instância diretamente. Os resultados da operação são os seguintes:
Podemos fazer algo antes de calcular. Usado: 1 resultado é: 3we pode fazer algo antes de calcular. Usado: 2 Resultado é: 1 Podemos fazer algo antes de calcular. Usado: 3 Resultado é: 24we podemos fazer algo antes de calcular. Usado: 4 Resultado é: 3
Dessa forma, implementamos a extensão do código sem modificar o código interno do calculatorImpl.
Em seguida, use o CGLIB para implementá -lo uma vez.
Primeiro, crie uma classe para implementar a interface do MethodInterceptor e substituir o método de interceptação. Outros códigos são semelhantes ao uso do proxy JDK, mas o processo de obtenção de objetos de proxy é diferente.
classe pública CGLIBProxy implementa MethodInterceptor {private Int Usetimes; destino de objeto privado; Public Object getInstance (objeto destino) {this.target = Target; Intensificador intensificador = new intensancer (); intensancer.SetSuperclass (this.target.getClass ()); intensificador.setCallback (this); return aprimor.create (); } @Override Public Object Intercept (objeto o, método do método, objeto [] Objetos, MethodProxy MethodProxy) lança arremesso {antes (); Resultado do objeto = métodProxy.invokesuper (O, objetos); depois(); resultado de retorno; } vazio privado antes () {System.out.println ("Podemos fazer algo antes de calcular."); } private void após () {utetimes ++; System.out.println ("Usado:"+usetimes+"Times"); }}Teste:
classe pública testCglibProxy {public static void main (string [] args) {cglibProxy cglibProxy = new CGLIBProxy (); ICsulator calcular = (iCulator) cglibProxy.getInstance (new CalculatorImpl ()); int resultado = calcular.add (1,2); System.out.println ("O resultado é:"+resultado); resultado = calcular.subtract (3,2); System.out.println ("O resultado é:"+resultado); resultado = calcular.Multiply (4,6); System.out.println ("O resultado é:"+resultado); resultado = calcular.Devide (6,2); System.out.println ("O resultado é:"+resultado); }}Os resultados da operação são os seguintes:
Podemos fazer algo antes de calcular. Usado: 1 resultado é: 3we pode fazer algo antes de calcular. Usado: 2 Resultado é: 1 Podemos fazer algo antes de calcular. Usado: 3 Resultado é: 24we podemos fazer algo antes de calcular. Usado: 4 Resultado é: 3
Agora obtemos o mesmo resultado. (São necessários dois pacotes, cglib-2.2.2.jar asm-3.3.jar)
Ambos os métodos têm seus próprios pontos fortes. O JDK Proxy precisa configurar uma interface antes de implementar o proxy. Essa é sua desvantagem e sua vantagem. A desvantagem é que isso será um pouco mais problemático e não pode procurar aqueles que já estão encapsulados e não implementam a interface. O método CGLIB Proxy não requer o uso de interfaces. Mas é também por isso que o proxy JDK intercepta apenas métodos que substituem interfaces da classe, enquanto o CGLIB intercepta todas as chamadas de método da classe. Ambos têm seus prós e contras, portanto, circunstâncias específicas precisam ser analisadas. Na primavera, dois modos de proxy são usados misturados.