Java Reflection-Proxies dinâmicos

usando o java Reflection, você cria implementações dinâmicas de interfaces em tempo de execução. Você faz isso usando a classe java.lang.reflect.Proxy. O nome desta classe é por isso que me refiro a essas implementações de interface dinâmica como proxies dinâmicos. Proxies dinâmicos podem ser usados para muitos propósitos diferentes, por exemplo, conexão de banco de dados e gerenciamento de transações, objetos mock dinâmicos para teste de unidade e outros fins de interceptação de métodos semelhantes ao AOP.

criando Proxies

você cria proxies dinâmicos usando o método Proxy.newProxyInstance(). Os métodos newProxyInstance() levam 3 parâmetros:

  1. o ClassLoader que é “carregar” a classe proxy dinâmica.
  2. uma matriz de interfaces para implementar.
  3. An InvocationHandler para encaminhar todas as chamadas de métodos no proxy para.

aqui está um exemplo:

depois de executar este código, a variável proxy contém uma implementação dinâmica da interface MyInterface. Todas as chamadas para o proxy serão encaminhadas para a implementação handler da interface geral InvocationHandler. Invocationhandler’s são cobertos i a próxima seção.

Invocationhandler’s

como mencionado anteriormente, você deve passar uma implementação InvocationHandler para o método Proxy.newProxyInstance(). Todas as chamadas de método para o proxy dinâmico são encaminhadas para esta implementação InvocationHandler. Aqui é como o InvocationHandler interface de procura:

public interface InvocationHandler{ Object invoke(Object proxy, Method method, Object args) throws Throwable;}

Aqui está um exemplo de implementação:

public class MyInvocationHandler implements InvocationHandler{ public Object invoke(Object proxy, Method method, Object args) throws Throwable { //do something "dynamic" }}

O proxy parâmetro passado para o invoke() método é dinâmico proxy objecto que implementa a interface. Na maioria das vezes você não precisa desse objeto.

o objeto Method passado para o método invoke() representa o método chamado na interface que o proxy dinâmico implementa. A partir do objeto Method você pode obter o nome do método, tipos de parâmetros, tipo de retorno, etc. Consulte o texto sobre métodos para obter mais informações.

a matriz Object args contém os valores dos parâmetros passados para o proxy quando o método na interface implementada foi chamado. Nota: as primitivas (int, long etc) na interface implementada são agrupadas em suas contrapartes de objeto (Integer, Long etc.).

Conhecidos Casos de Uso

Dinâmica proxies são conhecidos para ser usado por, no mínimo, as seguintes finalidades:

  • Conexão de banco de dados e Gestão de Transacções
  • Dinâmica de Objetos de Simulação para o Teste de Unidade
  • Adaptação de DI Recipiente Personalizada de Fábrica Interfaces
  • AOP-como Método de Interceptação

Conexão de Banco de dados e Gestão de Transacções

O Spring framework tem uma transação de proxy que pode iniciar e commit / rollback de uma transação para você. Como isso funciona é descrito com mais detalhes no texto Advanced Connection and Transaction Demarcation and Propagation , então vou descrevê-lo apenas brevemente. A sequência de chamadas torna-se algo assim:

objetos Mock dinâmicos para teste de unidade

as ferramentas de teste Butterfly usam proxies dinâmicos para implementar stubs, mocks e proxies dinâmicos para teste de unidade. Ao testar uma classe A que usa outra Classe B (interface realmente), você pode passar uma implementação simulada de B Em A Em vez de um B real. Todas as chamadas de método em B agora são gravadas e você pode definir quais valores de retorno o mock B deve retornar.

além disso, as ferramentas de teste Butterfly permitem que você envolva um B real em um B simulado, para que todas as chamadas de método no mock sejam gravadas e, em seguida, encaminhadas para o B real. O DAO não verá a diferença, e o DAO pode ler/gravar dados no banco de dados como de costume, pois o mock encaminha todas as chamadas para o banco de dados. Mas agora você pode verificar por meio do mock se o DAO usa a conexão corretamente, por exemplo, se o connection.close() é chamado (ou não chamado), se você esperava isso. Isso normalmente não é possível determinar a partir do valor de retorno de um DAO.

adaptação do contêiner DI às Interfaces de fábrica personalizadas

o contêiner borboleta do contêiner de injeção de dependência tem um recurso poderoso que permite injetar todo o contêiner em grãos produzidos por ele. Mas, como você não quer uma dependência da interface do contêiner, o contêiner é capaz de se adaptar a uma interface de fábrica personalizada do seu design. Você só precisa da interface. Sem implementação. Assim, a interface de fábrica e sua classe podem se parecer com isso:

public interface IMyFactory { Bean bean1(); Person person(); ...}

quando a classe MyAction chama métodos na instância IMyFactory injetada em seu construtor pelo contêiner, as chamadas de método são traduzidas em chamadas para o método IContainer.instance(), que é o método que você usa para obter instâncias do contêiner. Dessa forma, um objeto pode usar o Butterfly Container como uma fábrica em tempo de execução, em vez de apenas ter dependências injetadas em si mesmo no momento da criação. E isso sem ter nenhuma dependência em nenhuma interface específica do contêiner Butterfly.

interceptação de método semelhante ao AOP

a estrutura Spring permite interceptar chamadas de método para um determinado bean, desde que o bean implemente alguma interface. O Spring framework envolve o bean em um proxy dinâmico. Todas as chamadas para o bean são interceptadas pelo proxy. O proxy pode decidir chamar outros métodos em outros objetos antes, em vez de, ou depois de delegar a chamada de método para o bean envolvido.

Deixe uma resposta

O seu endereço de email não será publicado.