Comparando Spring AOP e AspectJ
1. Introdução
Atualmente, existem várias bibliotecas de AOP disponíveis e elas precisam responder a várias perguntas:
-
É compatível com meu aplicativo existente ou novo?
-
Onde posso implementar o AOP?
-
Com que rapidez ele será integrado ao meu aplicativo?
-
Qual é a sobrecarga de desempenho?
Neste artigo, veremos como responder a essas perguntas e apresentaremos Spring AOP e AspectJ - os dois frameworks AOP mais populares para Java.
2. Conceitos AOP
Antes de começar, vamos fazer uma revisão rápida e de alto nível dos termos e conceitos principais:
-
Aspecto - ** um código / recurso padrão que está espalhado por vários locais no aplicativo e normalmente é diferente da lógica de negócios real (por exemplo, gerenciamento de transações). Cada aspecto se concentra em uma funcionalidade transversal específica
-
Joinpoint - ** é um ponto específico durante a execução de programas, como execução de método, chamada de construtor ou atribuição de campo
-
Conselho - a ação executada pelo aspecto em um ponto de junção específico
-
Pointcut - uma expressão regular que corresponde a um ponto de junção. Cada vez que um ponto de junção corresponde a um corte de ponto, é executado um conselho especificado associado a esse corte
-
Tecelagem - o processo de vincular aspectos a objetos direcionados para criar um objeto recomendado
3. Spring AOP e AspectJ
Agora, vamos discutir Spring AOP e AspectJ em uma série de eixos - como recursos, objetivos, entrelaçamento, estrutura interna, pontos de junção e simplicidade.
3.1. Capacidades e objetivos
Simplificando, o Spring AOP e o AspectJ têm objetivos diferentes.
O Spring AOP visa fornecer uma implementação simples do AOP no Spring IoC para resolver os problemas mais comuns enfrentados pelos programadores. It is not intended as a complete AOP solution - só pode ser aplicado a beans gerenciados por um contêiner Spring.
Por outro lado,AspectJ is the original AOP technology which aims to provide complete AOP solution. é mais robusto, mas também significativamente mais complicado do que Spring AOP. Também é importante notar que AspectJ pode ser aplicado em todos os objetos de domínio.
3.2. Tecelagem
Tanto o AspectJ como o Spring AOP usam o tipo diferente de tecelagem que afeta seu comportamento em relação ao desempenho e à facilidade de uso.
O AspectJ utiliza três tipos diferentes de tecelagem:
-
Compile-time weaving: O compilador AspectJ toma como entrada o código-fonte de nosso aspecto e nosso aplicativo e produz arquivos de classe tecida como saída
-
Post-compile weaving: também conhecido como entrelaçamento binário. É usado para tecer arquivos de classe e arquivos JAR existentes com nossos aspectos
-
Load-time weaving: Isso é exatamente como a antiga tecelagem binária, com a diferença de que a tecelagem é adiada até que um carregador de classes carregue os arquivos de classe para a JVM
Para obter informações mais detalhadas sobre o próprio AspectJ,head on over to this article.
Como AspectJ usa tempo de compilação e entrelaçamento de tempo de carga de classe,Spring AOP makes use of runtime weaving.
Com a tecelagem em tempo de execução, os aspectos são tecidos durante a execução do aplicativo usando proxies do objeto de destino - usando o proxy dinâmico JDK ou o CGLIB (que serão discutidos no próximo ponto):
3.3. Estrutura Interna e Aplicação
Spring AOP é uma estrutura de AOP baseada em proxy. Isso significa que, para implementar aspectos dos objetos de destino, ele criará proxies desse objeto. Isso é alcançado usando uma das duas maneiras:
-
Proxy dinâmico JDK - a maneira preferida para o Spring AOP. Sempre que o objeto de destino implementa até uma interface, o proxy dinâmico JDK será usado
-
Proxy CGLIB - se o objeto de destino não implementar uma interface, o proxy CGLIB pode ser usado
Podemos aprender mais sobre os mecanismos de proxy Spring AOP emthe official docs.
AspectJ, por outro lado, não faz nada em tempo de execução, pois as classes são compiladas diretamente com os aspectos.
E então, ao contrário do Spring AOP, ele não requer nenhum padrão de design. Para tecer os aspectos do código, ele apresenta seu compilador conhecido como AspectJ (ajc), por meio do qual compilamos nosso programa e o executamos fornecendo uma pequena biblioteca de tempo de execução (<100K).
3.4. Joinpoints
Na seção 3.3, mostramos que o Spring AOP é baseado em padrões de proxy. Por esse motivo, ele precisa subclassificar a classe Java de destino e aplicar preocupações transversais de acordo.
Mas isso vem com uma limitação. We cannot apply cross-cutting concerns (or aspects) across classes that are “final” because they cannot be overridden and thus it would result in a runtime exception.
O mesmo se aplica aos métodos estáticos e finais. Os aspectos da primavera não podem ser aplicados a eles porque não podem ser substituídos. Portanto, o Spring AOP, devido a essas limitações, suporta apenas pontos de junção de execução de método.
No entanto,AspectJ weaves the cross-cutting concerns directly into the actual code before runtime. Ao contrário do Spring AOP, ele não requer subclasse do objeto direcionado e, portanto, oferece suporte a muitos outros pontos de junção também. A seguir, é apresentado o resumo dos pontos de junção suportados:
Joinpoint | Spring AOP com suporte | Compatível com AspectJ |
---|---|---|
Chamada de método |
No |
Yes |
Execução do Método |
Yes |
Yes |
Chamada de Construtor |
No |
Yes |
Execução do Construtor |
No |
Yes |
Execução do inicializador estático |
No |
Yes |
Inicialização de objeto |
No |
Yes |
Referência de campo |
No |
Yes |
Trabalho de campo |
No |
Yes |
Execução do manipulador |
No |
Yes |
Execução de conselhos |
No |
Yes |
Também é importante notar que no Spring AOP, aspectos não são aplicados ao método chamado dentro da mesma classe.
Isso, obviamente, porque quando chamamos um método dentro da mesma classe, então não estamos chamando o método do proxy que Spring AOP fornece. Se precisarmos dessa funcionalidade, precisamos definir um método separado em beans diferentes ou usar o AspectJ.
3.5. Simplicidade
O Spring AOP é obviamente mais simples porque não introduz nenhum compilador extra ou entrelaçamento entre o nosso processo de construção. Ele usa tecelagem em tempo de execução e, portanto, integra-se perfeitamente ao nosso processo de compilação usual. Embora pareça simples, ele funciona apenas com beans gerenciados pelo Spring.
No entanto, para usar o AspectJ, precisamos apresentar o compilador AspectJ (ajc) e reempacotar todas as nossas bibliotecas (a menos que mudemos para pós-compilação ou entrelaçamento no tempo de carregamento).
Isso é, obviamente, mais complicado que o anterior - porque apresenta o AspectJ Java Tools (que inclui um compilador (ajc), um depurador (ajdb), um gerador de documentação (ajdoc), um navegador de estrutura de programa (ajbrowser)) que nós precisa se integrar ao nosso IDE ou à ferramenta de construção.
3.6. atuação
No que diz respeito ao desempenho,compile-time weaving is much faster than runtime weaving. O Spring AOP é uma estrutura baseada em proxy, portanto, há a criação de proxies no momento da inicialização do aplicativo. Além disso, existem mais algumas invocações de métodos por aspecto, o que afeta negativamente o desempenho.
Por outro lado, AspectJ tece os aspectos no código principal antes que o aplicativo seja executado e, portanto, não há sobrecarga de tempo de execução adicional, ao contrário do Spring AOP.
Por essas razões, obenchmarks sugere que AspectJ é quase 8 a 35 vezes mais rápido que Spring AOP.
4. Sumário
Esta tabela rápida resume as principais diferenças entre o Spring AOP e o AspectJ:
Spring AOP | AspectJ |
---|---|
Implementado em Java puro |
Implementado usando extensões da linguagem de programação Java |
Não há necessidade de processo de compilação separado |
Necessita do compilador AspectJ (ajc), a menos que o LTW esteja configurado |
Apenas a tecelagem em tempo de execução está disponível |
A tecelagem em tempo de execução não está disponível. Suporta Weaving em tempo de compilação, pós-compilação e tempo de carregamento |
Menos poderoso - suporta apenas tecelagem de nível de método |
Mais poderoso - pode tecer campos, métodos, construtores, inicializadores estáticos, classes / métodos finais, etc ... |
Só pode ser implementado em beans gerenciados pelo contêiner Spring |
Pode ser implementado em todos os objetos de domínio |
Suporta apenas pontos de corte de execução de método |
Suporte a todos os pontos de corte |
Proxies são criados de objetos direcionados e aspectos são aplicados a esses proxies |
Aspectos são integrados diretamente no código antes que o aplicativo seja executado (antes do tempo de execução) |
Muito mais lento que AspectJ |
Melhor performance |
Fácil de aprender e aplicar |
Comparativamente mais complicado do que Spring AOP |
5. Escolhendo a Estrutura Certa
Se analisarmos todos os argumentos apresentados nesta seção, começaremos a entender que não é de forma alguma que um framework é melhor do que outro.
Simplificando, a escolha depende muito de nossos requisitos:
-
Framework: se o aplicativo não estiver usando o framework Spring, então não temos opção a não ser abandonar a ideia de usar Spring AOP porque ele não pode gerenciar nada que esteja fora do alcance do container spring. No entanto, se nosso aplicativo é criado inteiramente usando o framework Spring, então podemos usar Spring AOP, pois é simples de aprender e aplicar
-
Flexibilidade: Dado o suporte limitado ao ponto de junção, o Spring AOP não é uma solução completa, mas resolve os problemas mais comuns que os programadores enfrentam. Embora se quisermos aprofundar e explorar o AOP até sua capacidade máxima e desejar o suporte de uma ampla variedade de pontos de junção disponíveis, o AspectJ é a escolha
-
Desempenho: se estivermos usando aspectos limitados, existem diferenças de desempenho triviais. Mas às vezes há casos em que um aplicativo tem mais de dezenas de milhares de aspectos. Nesses casos, não gostaríamos de usar tecelagem em tempo de execução, por isso seria melhor optar pelo AspectJ. AspectJ é conhecido por ser 8 a 35 vezes mais rápido que o Spring AOP
-
Melhor de ambos: esses dois frameworks são totalmente compatíveis entre si. Sempre podemos tirar proveito do Spring AOP sempre que possível e ainda usar AspectJ para obter suporte de pontos de junção que não são suportados pelo anterior
6. Conclusão
Neste artigo, analisamos o Spring AOP e o AspectJ, em várias áreas-chave.
Comparamos as duas abordagens da AOP, tanto na flexibilidade quanto na facilidade com que elas se encaixam em nosso aplicativo.