introduzir
Como todos sabemos, a AOP (programação orientada para a seção) é um dos recursos das estruturas de mola. A AOP fornece escalabilidade extremamente alta, definindo preocupações de corte cruzado. Então, como a AOP funciona na primavera? Quando você só pode usar o Java Core, mas precisa da tecnologia AOP, a resposta a essa pergunta se torna extremamente crítica. Além disso, em entrevistas para posições técnicas avançadas, essas perguntas geralmente aparecem como perguntas de teste. Olha, meu amigo participou recentemente de uma entrevista e foi feita uma pergunta tão difícil - como implementar a AOP sem usar as bibliotecas da primavera e do relacionado, e apenas Java Core. Portanto, fornecerei um esboço neste artigo para ajudá -lo a entender como implementar uma AOP usando o Core Java (é claro, esta AOP possui certas limitações funcionais). Observe que este artigo não é um estudo comparativo da Spring AOP e Java AOP, mas um tutorial sobre a implementação da AOP com a ajuda de padrões de design inerentes no Java Core.
Acredito que os leitores já sabem o que é a AOP e como usá -lo na estrutura da primavera; portanto, este artigo se concentra apenas em como implementar a AOP sem usar a primavera. Primeiro de tudo, devemos saber que a primavera usa duas tecnologias: JDK Proxy e CGLIB para implementar a AOP. O proxy dinâmico do JDK fornece uma maneira flexível de conectar um método e executar operações especificadas, mas deve haver uma restrição ao executar operações: uma interface relacionada e a classe de implementação da interface devem ser fornecidas primeiro. Prática para criar conhecimento verdadeiro, vamos entender essa frase através de um caso! Agora existe um programa de calculadora para fazer algumas operações de matemática. Vamos considerar a função de divisão. A pergunta neste momento é: se a estrutura principal já tiver um código para implementar a divisão, podemos seqüestrar e executar verificação adicional quando o código for executado? A resposta é sim, e vou provar isso com o snippet de código fornecido abaixo. Primeiro, vejamos o código da interface básica:
Calculadora de interface pública {public int calcular (int a, int b);}O código desta classe de implementação da interface é o seguinte:
classe pública calculatorImpl implementa a calculadora {@Override public int calcular (int a, int b) {return a/b; }}Supondo que não possamos reparar o código acima ou fazer alterações na biblioteca principal, como podemos implementar perfeitamente a função de verificação? Por que não experimentar a função de proxy dinâmica do JDK.
classe pública SomeHandler implementa InvocationHandler {// Código omitido para simplificar… .. @Override Public Object Invoke (Proxy de objeto, método do método, objeto [] params) lança arremesso {// sua validação de negócios complexa e resultado lógico do objeto = Method.inVoke (TargetObject, params); resultado de retorno; }}Vamos ver como a função de verificação implementada pelo JDK Dynamic Proxy funciona através da classe de teste.
public static void main (string [] args) {calculatorImpl calcimpl = new calculatorImpl (); Calculadora proxied = (calculadora) proxyfactory.getProxy (calculator.class, calcimpl, new SomeHandler (calcimpl)); int resultado = proxied.calculate (20, 10); System.out.println ("resultado final :::" + resultado); }A partir dos resultados, podemos ver que, simplesmente implementando a poderosa interface InvocationHandler, podemos obter uma implementação de lojas. De acordo com a documentação do JDK, a interface InvocationHandler usa uma instância de proxy para lidar com uma chamada de método.
Agora sabemos que o método Invoke () de InvocationHandler pode nos ajudar a resolver o problema. Então, vamos resolver um novo problema - como podemos executar operações antes e depois da execução do método? Para colocá -lo mais especificamente, podemos conectar um método adicionando vários AOPs (antes, depois, ao redor) (nota do tradutor: o texto original é adicionar vários AOPS, mas acho que o manipulador atua como um aspecto)? A resposta também é sim. Siga as etapas abaixo para criar um modelo de código simplificado para atender a este requisito:
Duas maneiras de implementar a AOP:
1. Implementação dinâmica de proxy fornecida pelo JDK
interface
Public Interface UserBean {void getUser (); Void addUser (); void updateUser (); void DeleteUser (); } Classe de implementação original
classe pública userBeanImpl implementa o userbean {private string user = null; public userBeanImpl () {} public userBeanImpl (string user) {this.user = user; } public string getUserName () {return user; } public void getUser () {System.out.println ("Este é o método getUser ()!"); } public void setUser (string user) {this.User = user; System.out.println ("Este é o método setUser ()!"); } public void addUser () {System.out.println ("Este é o método addUser ()!"); } public void updateUser () {System.out.println ("Este é o método updateUser ()!"); } public void DeleteUser () {System.out.println ("Este é o método deleteUser ()!"); }} Classe de agente
importar java.lang.reflect.invocationHandler; importar java.lang.reflect.method; importar java.lang.reflect.proxy; importar com.cignacmc.finance.bean.userbeanimpl; classe pública UserBeanProxy implementa InvocationHandler {Private Object TargetObject; public userBeanProxy (Object TargetObject) {this.TargeGetObject = TargetObject; } Public Object Invoke (proxy do objeto, método do método, objeto [] args) lança arremesso {userBeanImpl userBean = (userBeanImpl) TargetObject; String userName = userBean.getUserName (); Resultado do objeto = nulo; // julgamento de permissão se (nome de usuário! = Null &&! "". Equals (nome de usuário)) {resultado = method.invoke (TargetObject, args); } resultado de retorno; }}
Classe de teste
importar java.lang.reflect.proxy; importação com.cignacmc.finance.bean.userbean; importar com.cignacmc.finance.bean.userbeanimpl; importar com.cignacmc.finance.proxy.userbeanproxy; classe pública proxyexe {public static void main (string [] args) {system.out.println ("provado ........."); UserBeanImpl TargetObject = new UserBeanImpl ("Bob Liang"); UserBeanProxy proxy = new UserBeanProxy (TargetObject); // gerar proxy objeto userBean objeto = (userbean) proxy.newproxyInstance (TargetObject.getClass (). GetClassLoader (), TargetObject.getClass (). GetInterfaces (), proxy); object.addUser (); System.out.println ("sem comprovado ............"); TargetObject = new UserBeanImpl (); proxy = new userBeanProxy (TargetObject); // gerar objeto proxy objeto = (userbean) proxy.newproxyInstance (TargetObject.getClass (). GetClassLoader (), TargoBject.getClass (). GetInterfaces (), proxy); object.addUser (); }}
Saída:
Provado ............ Este é o método addUser ()! Sem provado ..........
A partir do exemplo acima, o método chamado addUser () pode ser interceptado e processado com sucesso de acordo.
2. Crie aula de proxy através do CGLIB
A vantagem é que nosso objeto de destino não exige que a classe primitiva da interface seja implementada.
classe pública clientbean {private string name = null; public clientBean () {} public clientBean (nome da string) {this.name = name; } public void addClient () {System.out.println ("Este é o método addClient ()!"); } public void deleteClient () {System.out.println ("Este é o método deleteClient ()!"); } public void getClient () {System.out.println ("Este é o método getClient ()!"); } public void getClient () {System.out.println ("Este é o método getClient ())!"); } public void updateClient () {System.out.println ("Este é o método updateClient ()!"); } public String getClientName () {Return Name; } public void setClientName (nome da string) {this.name = name; }} Classe de agente
importar java.lang.reflect.method; importação com.cignacmc.finance.bean.clientBean; importação net.sf.cglib.proxy.enhancer; importação net.sf.cglib.proxy.methodintercept; importação net.sf.cglib.proxy.methodintercept; importação net.sf.cglib.proxy.methodProxy; classe pública CGLIBProxy implementa MethodInterceptor {Private Object TargetObject; Public Object CreateProxyObject (Object TargetObject) {this.TargeGetObject = TargetObject; Intensificador intensificador = new intensancer (); intensancer.SetSuperclass (this.targeGeTObject.getClass ()); intensificador.setCallback (this); return aprimor.create (); } interceptação pública de objeto (proxy do objeto, método do método, objeto [] args, métodProxy MethodProxy) lança arremesso {clientBean clientBean = (clientbean) TargetObject; String userName = clientBean.getClientName (); Resultado do objeto = nulo; if (nome de usuário! = null &&! "". Equals (nome de usuário)) {resultado = method.invoke (TargetObject, args); } resultado de retorno; }} Classe de teste
importar java.lang.reflect.proxy; importação com.cignacmc.finance.bean.clientBean; importação com.cignacmc.finance.bean.userbean; importar com.cignacmc.finance.bean.userbeanimpl; importar com.cignacmc.finance.proxy.cglibProxy; importar com.cignacmc.finance.proxy.userbeanproxy; classe pública proxyexe {public static void main (string [] args) {System.out.println ("........ proxy cglib ............"); System.out.println ("comprovado ..............."); CGLIBPROXY CProxy = new CGlibProxy (); ClientBean ClientBean = (ClientBean) CProxy.CreateProxyObject (New ClientBean ("Bob Liang")); clientBean.addclient (); System.out.println ("sem comprovado ..............."); CProxy = new CGlibProxy (); ClientBean = (ClientBean) CProxy.CreateProxyObject (new ClientBean ()); clientBean.addclient (); }}
Saída:
..... CGLIB Proxy .................. provado ............ Este é o método addClient ()! Sem comprovado ............