Ao aprender o Spring, sabemos que o Spring tem duas ideias principais, uma é a IoC e a outra é AOP.Para a IoC, a injeção de dependência não precisa dizer muito, e para a AOP principal do Spring, não precisamos apenas saber como passar AOP para cumprir nossas funções, precisamos aprender mais sobre o princípio subjacente, e o princípio da AOP é o mecanismo de proxy dinâmico do java, portanto, este ensaio é uma revisão do mecanismo dinâmico do java.
No mecanismo de proxy dinâmico do java, existem duas classes ou interfaces importantes, uma é InvocationHandler (Interface), a outra é Proxy (Class), essa classe e interface são necessárias para alcançar nosso proxy dinâmico. Primeiro, vamos dar uma olhada em como a documentação de ajuda da API java descreve essas duas classes:
InvocationHandler:
InvocationHandler é a interface implementada pelo manipulador de invocação de uma instância de proxy.
Cada instância de proxy possui um manipulador de chamada associado. Quando um método é chamado em uma instância de proxy, a chamada de método é codificada e despachada para o método de chamada de seu manipulador de chamadas.
Cada classe de proxy dinâmico deve implementar a interface InvocationHandler e cada instância da classe de proxy é associada a um manipulador.Quando chamamos um método através do objeto proxy, a chamada do método será encaminhada para a interface do InvocationHandler Para chamar o método de chamada. Vamos olhar InvocationHandler apenas um método desta interface invocar métodos:
A invocação de objeto (proxy de objeto, método Method, args Object []) lança Throwable
Vemos que esse método aceita um total de três parâmetros, então o que esses três parâmetros representam?
Objeto da Invoke (Object Proxy, Método ,, Object [] args) throws Throwable Proxy : se referir ao objeto real que são agentes da Method, : refere-se a um objeto Método queremos chamar um método de um objeto real de args : referem-se ao O parâmetro é aceito ao chamar um método em um objeto real
Se você não entender, explicaremos esses parâmetros com mais profundidade por meio de um exemplo.
Em seguida, vamos dar uma olhada na classe Proxy:
O proxy fornece métodos estáticos para criar instâncias e classes de proxy dinâmicas e também é a superclasse de todas as classes de proxy dinâmico criadas por esses métodos.
A função da classe Proxy é criar dinamicamente uma classe de objeto proxy, que fornece muitos métodos, mas o mais utilizado é o método newProxyInstance :
public static Objeto newProxyInstance (carregador de ClassLoader, interfaces de classe <?> [], InvocationHandler h) lança IllegalArgumentException
Retorna uma instância de uma classe proxy para as interfaces especificadas que despacha invocações de método para o manipulador de invocação especificado.
A função desse método é obter um objeto proxy dinâmico, que recebe três parâmetros, vamos dar uma olhada no significado desses três parâmetros:
public static Objeto newProxyInstance (carregador de ClassLoader, interfaces de classe <?> [], InvocationHandler h) lança o carregador IllegalArgumentException : um objeto de ClassLoader, que define qual objeto de ClassLoader carregará as interfaces de objetos de proxy geradas : uma matriz de objetos de interface, representando O que eu quero é fornecer um conjunto de interfaces para os objetos de que preciso fazer proxy, se eu fornecer um conjunto de interfaces, o objeto proxy alegará implementar a interface (polimorfismo), para que eu possa chamar esse conjunto de interfaces O método é h : um objeto InvocationHandler, que indica a qual objeto InvocationHandler será associado quando meu objeto proxy dinâmico chamar o método
Bem, depois de introduzir essas duas interfaces (classes), vamos dar uma olhada em um exemplo para ver como é o nosso modelo de proxy dinâmico:
Primeiro, definimos uma interface do tipo Subject e declaramos dois métodos para ela:
assunto da interface pública { public void rent (); olá public void (String str); }
Em seguida, defina uma classe para implementar essa interface, essa classe é nosso objeto real, a classe RealSubject:
public class RealSubject implementa Subject { @Override public void rent () { System.out.println ( "Quero alugar minha casa" ); } @ Substituir public void hello (String str) { System.out.println ( "hello:" + str); } }
Em seguida, definiremos uma classe de proxy dinâmico.Como mencionado anteriormente, cada classe de proxy dinâmico deve implementar a interface InvocationHandler, portanto nossa classe de proxy dinâmico não é exceção:
classe pública DynamicProxy implementa InvocationHandler { // Este é o objeto real que queremos proxy de objeto privado ; // Método de construção, atribua o valor inicial ao objeto real que queremos proxy de proxy DynamicProxy público (objeto de objeto) { this .subject = subject; } @ Substituir public Object invoke (Object, Method, Method, Object [] args) lança Throwable { // Podemos adicionar algumas de nossas próprias operações antes de fazer o proxy de objetos reais System.out.println ("before rent house" ); System.out. println ( "Método:" + método); // Quando o objeto proxy chama o método do objeto real, ele automaticamente salta para o método de chamada do objeto manipulador associado ao objeto proxy para chamar method.invoke (subject, args); // Também podemos adicionar alguns após o objeto real do proxy Operação própria System.out.println ("após a locação" ); return null ; } }
Por fim, vamos dar uma olhada na nossa classe Client:
public class Client { public static void main (String [] args) { // O objeto real que queremos proxy Assunto realSubject = new RealSubject (); // Qual objeto real queremos proxy, passar o objeto e finalmente passar O objeto real para chamar seu método InvocationHandler manipulador = new DynamicProxy (realSubject); / * * O método newProxyInstance do proxy para criar nosso objeto proxy, vamos dar uma olhada nos três parâmetros * O primeiro parâmetro handler.getClass () .getClassLoader (), usamos o objeto ClassLoader da classe manipuladora para carregar nosso objeto proxy * O segundo parâmetro realSubject.getClass (). getInterfaces (), a interface que fornecemos aqui para o objeto proxy é a interface implementada pelo objeto real , Indicando que eu quero proxy do objeto real, para que eu possa chamar os métodos neste conjunto de interfaces * O terceiro manipulador de parâmetros, associamos esse objeto proxy ao objeto InvocationHandler acima * / Subject subject =(Assunto) Proxy.newProxyInstance ( manipulador.getClass (). GetClassLoader (), realSubject .getClass (). GetInterfaces (), manipulador); System.out.println (subject.getClass (). GetName ()); subject.rent (); subject.hello ( "mundo" ); } }
Vamos dar uma olhada na saída do console primeiro:
$ Proxy0 antes da casa de aluguel Método: public abstract void com.xiaoluo.dynamicproxy.Subject.rent () Quero alugar minha casa após alugar casa antes da casa de aluguel Método: public abstract void com.xiaoluo.dynamicproxy.Subject.hello (java. hang : world after rent house
Vamos primeiro dar uma olhada na coisa $ Proxy0. Vemos que essa coisa é impressa por System.out.println (subject.getClass (). GetName ()); foi por isso que retornamos esse objeto proxy O nome da classe é assim?
Assunto do assunto = (Assunto) Proxy.newProxyInstance (handler.getClass (). GetClassLoader (), realSubject
.getClass (). GetInterfaces (), handler);
Talvez eu tenha pensado que o objeto proxy retornado seria um objeto do tipo Subject ou um objeto de InvocationHandler, mas o resultado não é. Primeiro, vamos explicar por que podemos convertê-lo em um objeto do tipo Subject aqui? O motivo é que, no segundo parâmetro do método newProxyInstance, fornecemos um conjunto de interfaces para o objeto proxy, então meu objeto proxy implementará esse conjunto de interfaces. Nesse momento, é claro que podemos converter o objeto proxy em conversão obrigatória de tipo Para qualquer um desse grupo de interfaces, porque a interface aqui é do tipo Assunto, ela pode ser convertida no tipo Assunto .
Ao mesmo tempo, devemos lembrar que o objeto proxy criado pelo Proxy.newProxyInstance é um objeto gerado dinamicamente quando a jvm está em execução.Não é o nosso tipo InvocationHandler nem o tipo de grupo de interface que definimos, mas está em execução. Um objeto gerado dinamicamente e o método de nomeação está neste formato, começando com $, proxy está em, e o último número indica o rótulo do objeto .
Então vamos dar uma olhada nessas duas frases
subject.rent ();
subject.hello ("mundo");
Aqui está o método do tipo de interface implementada por meio do objeto proxy: neste momento, o programa passará para o método de chamada no manipulador associado ao objeto proxy a ser executado, e nosso objeto manipulador aceita um RealSubject. O parâmetro type indica que é esse objeto real que eu quero proxy, portanto, neste momento, o método de chamada no manipulador será chamado para executar:
public Object invoke (Object, Method, Method, Object [] args) lança Throwable { // Podemos adicionar algumas de nossas próprias operações antes de fazer o proxy do objeto real System.out.println ("before rent house" ); System.out.println ( "Method:" + method); // Quando o objeto proxy chama o método do objeto real, ele automaticamente salta para o método de chamada do objeto manipulador associado ao objeto proxy para chamar method.invoke (subject, args); / / Após o proxy de objetos reais, também podemos adicionar algumas de nossas próprias operações System.out.println ("after rent house" ); return null ; }
Vemos que quando o método do objeto real é chamado por meio do objeto proxy, podemos adicionar algumas de nossas próprias operações antes e depois do método, e vemos que nosso objeto de método é assim:
resumo público vazio com.xiaoluo.dynamicproxy.Subject.rent () resumo público vazio com.xiaoluo.dynamicproxy.Subject.hello (java.lang.String)
Por acaso são dois métodos em nossa interface Subject, o que prova que, quando eu chamo um método por meio de um objeto proxy, na verdade é delegado que ele é invocado pelo método invoke do objeto manipulador ao qual está associado, não por mim mesmo. Chamada real, mas ligue através do agente.
Este é o nosso mecanismo de proxy dinâmico java
Este ensaio explica o mecanismo de proxy dinâmico em java em detalhes.Este ponto de conhecimento é muito importante, incluindo nosso Spring AOP, que é implementado através do mecanismo de proxy dinâmico, portanto, devemos entender bem o mecanismo de proxy dinâmico.