Proxy dinâmico JAVA
modo proxy
O padrão de agente é um padrão de design Java comumente usado. Sua característica é que a classe de agente e a classe delegada têm a mesma interface. A classe de agente é responsável principalmente por pré-processar mensagens para a classe delegada, filtrar mensagens e encaminhar mensagens para a classe delegada. e processando mensagens posteriormente. Geralmente há uma associação entre uma classe proxy e uma classe delegada. Um objeto de uma classe proxy está associado a um objeto de uma classe delegada. O objeto da classe proxy em si não implementa o serviço, mas chama os métodos relevantes. do objeto da classe delegada. Fornece serviços específicos.
De acordo com o período de criação do agente, a classe de agente pode ser dividida em dois tipos.
Proxy estático: criado por programadores ou gerado automaticamente por uma ferramenta específica e depois compilado. Antes de o programa ser executado, o arquivo .class da classe proxy já existe.
Proxy dinâmico: criado dinamicamente usando o mecanismo de reflexão quando o programa está em execução.
Primeiro, dê uma olhada no proxy estático:
1.Contagem.java
Copie o código do código da seguinte forma:
pacote net.battier.dao;
/**
* Defina uma interface de conta
*
* @autor Administrador
*
*/
interface pública Contagem {
//Ver método da conta
public void queryCount();
//Modifica o método da conta
public void updateCount();
}
2.ContImpl.java
Copie o código do código da seguinte forma:
pacote net.battier.dao.impl;
importar net.battier.dao.Count;
/**
* Classe delegada (incluindo lógica de negócios)
*
* @autor Administrador
*
*/
A classe pública CountImpl implementa Count {
@Substituir
public void queryCount() {
System.out.println("Ver método de conta...");
}
@Substituir
public void updateCount() {
System.out.println("Modificar método de conta...");
}
}
ContagemProxy.java
pacote net.battier.dao.impl;
importar net.battier.dao.Count;
/**
* Esta é uma classe proxy (classe de implementação CountImpl aprimorada)
*
* @autor Administrador
*
*/
A classe pública CountProxy implementa Count {
privado CountImpl countImpl;
/**
* Substitua o construtor padrão
*
* @param contagemImpl
*/
public CountProxy(CountImpl contagemImpl) {
this.countImpl = contagemImpl;
}
@Substituir
public void queryCount() {
System.out.println("Antes do processamento da transação");
// Chama o método da classe delegada;
contagemImpl.queryCount();
System.out.println("Após processamento da transação");
}
@Substituir
public void updateCount() {
System.out.println("Antes do processamento da transação");
// Chama o método da classe delegada;
contagemImpl.updateCount();
System.out.println("Após processamento da transação");
}
}
3. TestCount.java
Copie o código do código da seguinte forma:
pacote net.battier.test;
importar net.battier.dao.impl.CountImpl;
importar net.battier.dao.impl.CountProxy;
/**
*Aula de contagem de testes
*
* @autor Administrador
*
*/
classe pública TestCount {
public static void main(String[] args) {
ContagemImpl contagemImpl = new ContagemImpl();
CountProxy countProxy = new CountProxy(countImpl);
contagemProxy.updateCount();
contagemProxy.queryCount();
}
}
Observando o código, você pode descobrir que cada classe de proxy pode servir apenas uma interface. Dessa forma, muitos proxies serão inevitavelmente gerados durante o desenvolvimento do programa. Além disso, todas as operações de proxy são as mesmas, exceto o método que eles chamam. deve ser repetido neste momento. A melhor maneira de resolver este problema é usar uma classe proxy para completar todas as funções do proxy. Nesse caso, um proxy dinâmico deve ser usado para completá-lo.
Vamos dar uma olhada no proxy dinâmico:
O proxy dinâmico JDK contém uma classe e uma interface:
Interface InvocationHandler:
interface pública InvocationHandler {
invocação de objeto público (proxy de objeto, método de método, objeto [] args) lança Throwable;
}
Descrição do parâmetro:
Proxy de objeto: refere-se ao objeto que está sendo proxy.
Método método: o método a ser chamado
Object[] args: parâmetros necessários ao chamar o método
Você pode pensar em uma subclasse da interface InvocationHandler como a classe de operação final de um proxy, substituindo ProxySubject.
Classe proxy:
A classe Proxy é uma classe especializada em operações de proxy. Esta classe pode ser usada para gerar dinamicamente classes de implementação para uma ou mais interfaces.
objeto estático público newProxyInstance (carregador ClassLoader, interfaces Class<?>[],
InvocationHandler h)
lança IllegalArgumentException
Descrição do parâmetro:
Carregador ClassLoader: carregador de classes
Classe<?>[] interfaces: obtém todas as interfaces
InvocationHandler h: Obtenha a instância da subclasse da interface InvocationHandler
Ps: carregador de classes
Uma instância da classe ClassLoader é necessária no método newProxyInstance() na classe Proxy, na verdade, corresponde ao carregador de classes.
Booststrap ClassLoader: Este carregador é escrito em C++ e não pode ser visto no desenvolvimento geral;
Extension ClassLoader: usado para carregar classes de extensão, geralmente correspondendo a classes no diretório jre/lib/ext;
AppClassLoader: (padrão) carrega a classe especificada pelo classpath, que é o carregador mais comumente usado.
proxy dinâmico
Em contraste com a classe de proxy estático, existe a classe de proxy dinâmico. O bytecode da classe de proxy dinâmico é gerado dinamicamente pelo mecanismo de reflexão Java quando o programa está em execução, sem a necessidade de os programadores escreverem manualmente seu código-fonte. As classes de proxy dinâmico não apenas simplificam o trabalho de programação, mas também melhoram a escalabilidade dos sistemas de software, porque o mecanismo de reflexão Java pode gerar qualquer tipo de classe de proxy dinâmico. A classe Proxy e a interface InvocationHandler no pacote java.lang.reflect fornecem a capacidade de gerar classes proxy dinâmicas.
Exemplo de proxy dinâmico:
1.BookFacade.java
Copie o código do código da seguinte forma:
pacote net.battier.dao;
interface pública BookFacade {
public void addBook();
}
2.BookFacadeImpl.java
Copie o código do código da seguinte forma:
pacote net.battier.dao.impl;
importar net.battier.dao.BookFacade;
classe pública BookFacadeImpl implementa BookFacade {
@Substituir
public void addBook() {
System.out.println("Método Adicionar livro...");
}
}
BookFacadeProxy.java
pacote net.battier.proxy;
importar java.lang.reflect.InvocationHandler;
importar java.lang.reflect.Method;
importar java.lang.reflect.Proxy;
/**
* Classe de proxy proxy dinâmico JDK
*
* @autor aluno
*
*/
classe pública BookFacadeProxy implementa InvocationHandler {
alvo de objeto privado;
/**
* Vincule o objeto delegado e retorne uma classe proxy
* @param alvo
* @retornar
*/
vinculação de objeto público (alvo do objeto) {
este.target = alvo;
//Obtém o objeto proxy
retornar Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //Para vincular a interface (isso é uma falha, cglib compensa essa falha)
}
@Substituir
/**
* Método de chamada
*/
invocação de objeto público (proxy de objeto, método de método, objeto [] args)
lança Arremessável {
Resultado do objeto=nulo;
System.out.println("A coisa começa");
//método de execução
resultado = método.invoke (alvo, argumentos);
System.out.println("Fim das coisas");
resultado de retorno;
}
}
3.TestProxy.java
Copie o código do código da seguinte forma:
pacote net.battier.test;
importar net.battier.dao.BookFacade;
importar net.battier.dao.impl.BookFacadeImpl;
importar net.battier.proxy.BookFacadeProxy;
classe pública TestProxy {
public static void main(String[] args) {
Proxy BookFacadeProxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
livroProxy.addBook();
}
}
No entanto, o proxy dinâmico do JDK depende da implementação da interface. Se algumas classes não implementarem a interface, o proxy JDK não poderá ser usado, portanto, o proxy dinâmico cglib deverá ser usado.
Proxy dinâmico Cglib
O mecanismo de proxy dinâmico do JDK só pode fazer proxy de classes que implementam interfaces. As classes que não podem implementar interfaces não podem implementar o proxy dinâmico do JDK. Seu princípio é gerar uma subclasse para a classe de destino especificada e substituir os métodos. , mas como a herança é usada, a classe modificada final não pode ser proxy.
Exemplo
1.BookFacadeCglib.java
Copie o código do código da seguinte forma:
pacote net.battier.dao;
interface pública BookFacade {
public void addBook();
}
2.BookCadeImpl1.java
Copie o código do código da seguinte forma:
pacote net.battier.dao.impl;
/**
* Esta é uma classe de implementação que não implementa a interface
*
* @autor aluno
*
*/
classe pública BookFacadeImpl1 {
public void addBook() {
System.out.println("Método comum para adicionar livros...");
}
}
3.BookFacadeProxy.java
Copie o código do código da seguinte forma:
pacote net.battier.proxy;
importar java.lang.reflect.Method;
importar net.sf.cglib.proxy.Enhancer;
importar net.sf.cglib.proxy.MethodInterceptor;
importar net.sf.cglib.proxy.MethodProxy;
/**
* Use proxy dinâmico cglib
*
* @autor aluno
*
*/
classe pública BookFacadeCglib implementa MethodInterceptor {
alvo de objeto privado;
/**
* Criar objeto proxy
*
* @param alvo
* @retornar
*/
objeto público getInstance(objeto alvo) {
este.target = alvo;
Aprimorador intensificador = novo Aprimorador();
realçador.setSuperclass(this.target.getClass());
//método de retorno de chamada
realçador.setCallback(this);
//Cria objeto proxy
retornar intensificador.create();
}
@Substituir
//método de retorno de chamada
interceptação de objeto público (objeto obj, método método, objeto [] args,
Proxy MethodProxy) lança Throwable {
System.out.println("A coisa começa");
proxy.invokeSuper(obj,args);
System.out.println("Fim das coisas");
retornar nulo;
}
}
4.TestCglib.java
Copie o código do código da seguinte forma:
pacote net.battier.test;
importar net.battier.dao.impl.BookFacadeImpl1;
importar net.battier.proxy.BookFacadeCglib;
classe pública TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
livroCglib.addBook();
}
}