No caso do Proxy Design Pattern , qual é a diferença entre o Dynamic Proxy do JDK e as APIs de geração de código dinâmico de terceiros, como o CGLib ?
Qual é a diferença entre usar as duas abordagens e quando devemos preferir uma à outra?
java
reflection
cglib
dynamic-proxy
KDjava
fonte
fonte
Respostas:
O proxy dinâmico do JDK pode fazer proxy apenas por interface (portanto, sua classe de destino precisa implementar uma interface, que também é implementada pela classe de proxy).
O CGLIB (e o javassist) podem criar um proxy por subclassificação. Nesse cenário, o proxy se torna uma subclasse da classe de destino. Não há necessidade de interfaces.
Portanto, os proxies Java Dynamic podem fazer proxy:
public class Foo implements iFoo
onde CGLIB pode fazer proxy:public class Foo
EDITAR:
Devo mencionar que, como javassist e CGLIB usam proxy por subclassificação, esse é o motivo pelo qual você não pode declarar métodos finais ou tornar a classe final ao usar estruturas que dependem disso. Isso impediria que essas bibliotecas permitissem subclassificar sua classe e substituir seus métodos.
fonte
Diferenças na funcionalidade
Os proxies JDK permitem implementar qualquer conjunto de interfaces durante a subclasse
Object
. Qualquer método de interface, maisObject::hashCode
,Object::equals
eObject::toString
é então encaminhado para umInvocationHandler
. Além disso, a interface da biblioteca padrãojava.lang.reflect.Proxy
é implementada.O cglib permite implementar qualquer conjunto de interfaces enquanto subclassifica qualquer classe não final. Além disso, os métodos podem ser substituídos opcionalmente, ou seja, nem todos os métodos não abstratos precisam ser interceptados. Além disso, existem diferentes maneiras de implementar um método. Ele também oferece uma
InvocationHandler
classe (em um pacote diferente), mas também permite chamar super métodos usando interceptores mais avançados, como por exemplo aMethodInterceptor
. Além disso, o cglib pode melhorar o desempenho por interceptações especializadas, comoFixedValue
. Certa vez, escrevi um resumo de diferentes interceptores para o cglib .Diferenças de desempenho
Os proxies JDK são implementados de forma bastante ingênua com apenas um distribuidor de interceptação, o
InvocationHandler
. Isso requer um envio de método virtual para uma implementação que nem sempre pode ser incorporada. O Cglib permite criar código de bytes especializado, o que às vezes pode melhorar o desempenho. Aqui estão algumas comparações para implementar uma interface com 18 métodos de stub:O tempo é anotado em nanossegundos com desvio padrão entre chaves. Você pode encontrar mais detalhes sobre o benchmark no tutorial do Byte Buddy , onde o Byte Buddy é uma alternativa mais moderna ao cglib. Além disso, observe que o cglib não está mais em desenvolvimento ativo.
fonte
Proxy dinâmico: implementações dinâmicas de interfaces em tempo de execução usando a API JDK Reflection .
Exemplo: O Spring usa proxies dinâmicos para transações da seguinte maneira:
O proxy gerado vem em cima do bean. Ele adiciona comportamento transnacional ao bean. Aqui, o proxy é gerado dinamicamente em tempo de execução usando a API do JDK Reflection.
Quando um aplicativo é parado, o proxy será destruído e teremos apenas interface e bean no sistema de arquivos.
No exemplo acima, temos interface. Mas na maior parte da implementação da interface não é melhor. Portanto, o bean não implementa uma interface; nesse caso, usamos herança:
Para gerar esses proxies, o Spring usa uma biblioteca de terceiros chamada CGLib .
Cglib ( C ode L eneration Lib rary) é construído no topo de ASM , este é utilizado principalmente a gerar feijão estendendo proxy e adiciona comportamento feijão nos métodos de proxy.
Exemplos para proxy dinâmico JDK e CGLib
Ref Primavera
fonte
Da documentação do Spring :
fonte