Java - Mecanismo detalhado do agente dinâmico

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:

Copiar código
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





Copiar código

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:

Copiar código
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); 
    } 
}
Copiar código

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:

Copiar código
 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 ; 
    } 

}
Copiar código

Por fim, vamos dar uma olhada na nossa classe Client:

Copiar código
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" ); 
    } 
}
Copiar código

Vamos dar uma olhada na saída do console primeiro:

Copiar código
$ 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
Copiar código

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:

Copiar código
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 ; 
    }
Copiar código

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.


Publicado 7 artigos originais · 69 elogios · mais de 200.000 visualizações

Acho que você gosta

Origin blog.csdn.net/u014320421/article/details/79770743
Recomendado
Clasificación