Porovnávanie jarných AOP a AspectJ
1. Úvod
V súčasnosti existuje viac dostupných knižníc AOP, ktoré musia byť schopné odpovedať na niekoľko otázok:
- Je kompatibilný s mojou existujúcou alebo novou aplikáciou?
- Kde môžem implementovať AOP?
- Ako rýchlo sa integruje do mojej aplikácie?
- Aká je réžia výkonu?
V tomto článku sa pozrieme na odpovede na tieto otázky a predstavíme si Spring AOP a AspectJ - dva najpopulárnejšie rámce AOP pre Javu.
2. Koncepty AOP
Než začneme, urobme si rýchlu kontrolu pojmov a základných pojmov na vysokej úrovni:
- Pomer strán - štandardný kód / funkcia, ktorá je rozptýlená na viacerých miestach v aplikácii a zvyčajne sa líši od skutočnej obchodnej logiky (napríklad Správa transakcií). Každý aspekt sa zameriava na konkrétnu prierezovú funkcionalitu
- Pripojovací bod - je to konkrétny bod počas vykonávania programov, ako je vykonávanie metódy, volanie konštruktora alebo priradenie poľa
- Rada - akcia vykonaná aspektom v konkrétnom spojovacom bode
- Bodový bod - regulárny výraz, ktorý sa zhoduje s bodom spojenia. Zakaždým, keď sa ktorýkoľvek bod spojenia zhoduje s bodom, vykoná sa špecifikovaná rada spojená s týmto bodom
- Tkanie - proces prepájania aspektov s cieľovými objektmi za účelom vytvorenia odporúčaného objektu
3. Jarné AOP a AspectJ
Teraz poďme diskutovať o Spring AOP a AspectJ naprieč mnohými osami - ako sú schopnosti, ciele, tkanie, vnútorná štruktúra, spojovacie body a jednoduchosť.
3.1. Schopnosti a ciele
Jednoducho povedané, jarné AOP a AspectJ majú odlišné ciele.
Cieľom jarného AOP je poskytnúť jednoduchú implementáciu AOP v rámci jarného IoC na riešenie najbežnejších problémov, ktorým programátori čelia. Nie je to zamýšľané ako úplné riešenie AOP - je možné ho použiť iba na fazuľu, ktorá je spravovaná nádobou Spring.
Na druhej strane, AspectJ je pôvodná technológia AOP, ktorej cieľom je poskytnúť úplné riešenie AOP. Je robustnejší, ale tiež podstatne komplikovanejší ako Spring AOP. Je tiež potrebné poznamenať, že AspectJ je možné použiť na všetky objekty domény.
3.2. Tkanie
AspectJ aj Spring AOP používajú odlišný typ tkania, ktorý ovplyvňuje ich správanie, pokiaľ ide o výkon a jednoduché použitie.
AspectJ využíva tri rôzne typy tkania:
- Tkanie v čase kompilácie: Kompilátor AspectJ berie ako vstup zdrojový kód nášho aspektu aj našej aplikácie a vytvára výstupné súbory triedy tkané ako výstup
- Postkompilované tkanie: Toto je tiež známe ako binárne tkanie. Používa sa na tkanie existujúcich súborov triedy a súborov JAR s našimi aspektmi
- Tkanie času načítania: Je to presne také isté ako predchádzajúce binárne tkanie, s tým rozdielom, že tkanie sa odkladá, kým nakladač tried nenačíta súbory triedy do JVM.
Podrobnejšie informácie o aspekte samotnom nájdete v tomto článku.
Pretože AspectJ používa tkanie času kompilácie a času načítania, Jarná AOP využíva runtime tkanie.
Pri runtime tkaní sú aspekty utkané počas vykonávania aplikácie pomocou proxy cieľového objektu - pomocou dynamického proxy JDK alebo CGLIB proxy (o ktorých sa pojednáva v ďalšom bode):

3.3. Vnútorná štruktúra a použitie
Jarný AOP je rámec AOP založený na proxy serveri. To znamená, že na implementáciu aspektov do cieľových objektov sa vytvoria proxy tohto objektu. To sa dá dosiahnuť jedným z dvoch spôsobov:
- JDK dynamic proxy - preferovaný spôsob pre Spring AOP. Kedykoľvek cieľový objekt implementuje čo i len jedno rozhranie, použije sa dynamický proxy server JDK
- CGLIB proxy - ak cieľový objekt neimplementuje rozhranie, je možné použiť CGLIB proxy
Viac informácií o mechanizmoch proxy servera AOP na jar sa môžeme dozvedieť z oficiálnych dokumentov.
AspectJ, na druhej strane, za behu nerobí nič, pretože triedy sú kompilované priamo s aspektmi.
A tak na rozdiel od jarného AOP nevyžaduje žiadne dizajnové vzory. Na prepojenie aspektov s kódom predstavuje svoj kompilátor známy ako kompilátor AspectJ (ajc), prostredníctvom ktorého kompilujeme náš program a potom ho spustíme zadaním malej (<100 kB) runtime knižnice.
3.4. Spojovacie body
V časti 3.3 sme ukázali, že jarný AOP je založený na proxy vzoroch. Z tohto dôvodu potrebuje podtriedu cieľovej triedy Java a zodpovedajúce uplatnenie prierezových problémov.
Prichádza však s obmedzením. Nemôžeme aplikovať prierezové záujmy (alebo aspekty) na triedy, ktoré sú „konečné“, pretože ich nemožno prepísať, a preto by to malo za následok výnimku za behu.
To isté platí pre statické a konečné metódy. Jarné aspekty sa na ne nemôžu vzťahovať, pretože ich nemožno prekonať. Preto Spring AOP z dôvodu týchto obmedzení podporuje iba spojovacie body vykonania metódy.
Avšak AspectJ zapája prierezové obavy priamo do skutočného kódu pred spustením. Na rozdiel od Spring AOP nevyžaduje podtriedu cieľového objektu, a teda podporuje aj mnoho ďalších spojovacích bodov. Nasleduje zoznam podporovaných spojovacích bodov:
Joinpoint | Jarný AOP podporovaný | AspectJ Podporované |
---|---|---|
Method Call | Nie | Áno |
Vykonanie metódy | Áno | Áno |
Výzva konštruktéra | Nie | Áno |
Konštruktor Poprava | Nie | Áno |
Statické spustenie inicializátora | Nie | Áno |
Inicializácia objektu | Nie | Áno |
Referenčné pole | Nie | Áno |
Priradenie poľa | Nie | Áno |
Vykonávanie psovoda | Nie | Áno |
Vykonávanie rád | Nie | Áno |
Je tiež potrebné poznamenať, že na jar AOP sa aspekty neuplatňujú na metódu nazývanú v rámci tej istej triedy.
Je to zjavne preto, že keď voláme metódu v rámci tej istej triedy, nevoláme metódu proxy, ktorú poskytuje Spring AOP. Ak potrebujeme túto funkcionalitu, musíme definovať samostatnú metódu v rôznych fazuliach alebo použiť AspectJ.
3.5. Jednoduchosť
Jarný AOP je zjavne jednoduchší, pretože medzi našim procesom vytvárania nezavádza žiadny ďalší kompilátor alebo tkáč. Používa runtime tkanie, a preto sa bezproblémovo integruje do nášho obvyklého procesu zostavovania. Aj keď to vyzerá jednoducho, funguje to iba s fazuľami, ktoré spravuje jar.
Ak však chcete používať AspectJ, je potrebné predstaviť kompilátor AspectJ (ajc) a znovu zabaliť všetky naše knižnice (pokiaľ neprepneme na tkanie po kompilácii alebo načítaní).
To je samozrejme komplikovanejšie ako to prvé - pretože predstavuje AspectJ Java Tools (ktoré zahŕňajú kompilátor (ajc), debugger (ajdb), generátor dokumentácie (ajdoc), prehliadač programovej štruktúry (ajbrowser)), ktorý musíte sa integrovať buď s našim IDE, alebo s nástrojom na zostavenie.
3.6. Výkon
Čo sa týka výkonu, tkanie v kompilácii je oveľa rýchlejšie ako tkanie za behu. Jarný AOP je rámec založený na proxy, takže pri spustení aplikácie dochádza k vytváraniu proxy. Existuje tiež niekoľko ďalších vyvolaných metód pre každý aspekt, čo negatívne ovplyvňuje výkon.
Na druhej strane AspectJ zapája aspekty do hlavného kódu pred vykonaním aplikácie, a teda na rozdiel od Spring AOP neexistuje žiadna ďalšia runtime réžia.
Z týchto dôvodov referenčné hodnoty naznačujú, že AspectJ je takmer približne 8 až 35-krát rýchlejší ako jarný AOP.
4. Zhrnutie
Táto rýchla tabuľka sumarizuje kľúčové rozdiely medzi Spring AOP a AspectJ:
Jarný AOP | AspektJ |
---|---|
Implementované v čistej Jave | Implementované pomocou rozšírení programovacieho jazyka Java |
Nie je potrebný samostatný proces kompilácie | Potrebuje kompilátor AspectJ (ajc), pokiaľ nie je nastavený LTW |
K dispozícii je iba tkanie za behu | Runtime tkanie nie je k dispozícii. Podporuje tkanie v čase kompilácie, po kompilácii a načítaní |
Menej výkonný - podporuje iba tkanie na úrovni metód | Výkonnejšie - dokáže tkať polia, metódy, konštruktory, statické inicializátory, výslednú triedu / metódy atď ... |
Dá sa implementovať iba na fazuľa spravovaná kontajnerom Spring | Možno implementovať na všetky objekty domény |
Podporuje iba bodové body vykonania metódy | Podpora všetkých bodových výrezov |
Proxy sú vytvorené z cieľových objektov a na tieto proxy sú aplikované aspekty | Aspekty sú votkané priamo do kódu pred spustením aplikácie (pred spustením) |
Oveľa pomalšie ako AspectJ | Lepší výkon |
Ľahko sa učia a uplatňujú | Pomerne komplikovanejšie ako Spring AOP |
5. Výber správneho rámca
Ak analyzujeme všetky argumenty uvedené v tejto časti, začneme chápať, že vôbec nie je to, že jeden rámec je lepší ako iný.
Jednoducho povedané, výber silno závisí od našich požiadaviek:
- Rámec: Ak aplikácia nepoužíva jarný rámec, nemáme inú možnosť, ako upustiť od myšlienky používať Spring AOP, pretože nedokáže spravovať nič, čo je mimo dosahu jarného kontajnera. Ak je však naša aplikácia vytvorená úplne pomocou jarného rámca, môžeme použiť jarný AOP, pretože je jednoduché sa ho učiť a aplikovať
- Flexibilita: Vzhľadom na obmedzenú podporu joinpoint nie je Spring AOP úplným riešením AOP, ale rieši najbežnejšie problémy, ktorým programátori čelia. Aj keď, ak sa chceme hlbšie zaoberať a využívať AOP na svoje maximálne možnosti a chceme podporu zo širokej škály dostupných spojovacích bodov, potom je voľbou AspectJ
- Výkon: Ak používame obmedzené aspekty, potom existujú triviálne rozdiely vo výkonnosti. Ale niekedy existujú prípady, keď aplikácia má viac ako desaťtisíce aspektov. V takýchto prípadoch by sme nechceli používať runtime tkanie, takže by bolo lepšie zvoliť AspectJ. Je známe, že AspectJ je 8 až 35-krát rýchlejší ako jarný AOP
- Najlepšie z oboch: Oba tieto rámce sú navzájom úplne kompatibilné. Vždy, keď je to možné, môžeme využiť výhody jarného AOP a stále používať AspectJ na získanie podpory spojovacích bodov, ktoré bývalý nepodporuje
6. Záver
V tomto článku sme analyzovali jarné AOP aj AspectJ v niekoľkých kľúčových oblastiach.
Porovnali sme dva prístupy k AOP z hľadiska flexibility, ako aj toho, ako ľahko sa zmestia do našej aplikácie.