No framework Spring, a Programação Orientada a Aspectos (AOP) utiliza dois mecanismos principasi de代理 para implementar a interceptação de métodos:
Proxy Dinâmico do JDK: Este mecanismo é utilizado para classes que implemnetam interfaces. O JDK fornece a classe Proxy que permite criar instâncias de proxy em tempo de execução.
Proxy Dinâmico do CGLib: Este mecanismo é aplicado a classes que não implementam qualquer enterface. O CGLib utiliza técnicas de manipulação de bytecode para gerar subclasses dinamicamente, interceptando as chamadas aos métodos da classe pai.
Implementação com Proxy Dinâmico do JDK
O primeiro passo consiste em definir uma interface e sua implementação:
</div><div>```
public class ServicoUsuarioImpl implements SistemaUsuario {
@Override
public void autenticar() {
System.out.println("Método autenticar executado");
}
@Override
public void encerrarSessao() {
System.out.println("Método encerrarSessao executado");
}
}
public InterceptadorMetodos(Object objetoAlvo) {
this.objetoAlvo = objetoAlvo;
}
@Override
public Object invoke(Object proxy, Method metodo, Object[] argumentos) throws Throwable {
System.out.println("Antes da execução do método");
Object resultado = metodo.invoke(objetoAlvo, argumentos);
System.out.println("Após a execução do método");
return resultado;
}
}
</div>Testando a implementação:
<div>```
@Test
public void testarProxyJDK() {
SistemaUsuario servico = new ServicoUsuarioImpl();
InterceptadorMetodos manipulador = new InterceptadorMetodos(servico);
SistemaUsuario proxy = (SistemaUsuario) Proxy.newProxyInstance(
servico.getClass().getClassLoader(),
servico.getClass().getInterfaces(),
manipulador
);
proxy.autenticar();
}
Implementação com CGLib
O JDK Dynamic Proxy possui uma limitação: só pode criar proxies para interfaces. O método newProxyInstance recebe um array de interfaces como segundo parâmetro.
Para classes que não implementam interfaces, o CGLib oferece uma solução eficiente. Esta biblioteca cria subclasses em tempo de execução e utiliza interceptação de métodos para executar código adicional antes e depois das chamadas aos métodos originais.
Criando o代理 do CGLib:
public Object criarProxy(Class classeAlvo) {
potenciador.setSuperclass(classeAlvo);
potenciador.setCallback(this);
return potenciador.create();
}
@Override
public Object intercept(Object objeto, Method metodo,
Object[] parametros, MethodProxy proxyMetodo) throws Throwable {
System.out.println("Pré-processamento CGLib");
Object resultado = proxyMetodo.invokeSuper(objeto, parametros);
System.out.println("Pós-processamento CGLib");
return resultado;
}
}
</div>Testando com CGLib:
<div>```
@Test
public void testarProxyCGLib() {
CriadorProxyCGLib criador = new CriadorProxyCGLib();
ServicoUsuarioImpl servicoProxy = (ServicoUsuarioImpl)
criador.criarProxy(ServicoUsuarioImpl.class);
servicoProxy.autenticar();
}