A számítástechnikában az aspektus-orientált programozás (Aspect-oriented programming: AOP) egy olyan programozási paradigma, amelynek az a célja, hogy növelje a modularitást azáltal, hogy lehetővé teszi a különböző területeket érintő problémák elkülönítését . Ez úgy történik, hogy további viselkedést ad a meglévő kódhoz (egy úgynevezett tanácsot), anélkül, hogy módosítaná magát a kódot. Ehelyett külön meghatározza, hogy melyik kódot módosítsa egy "pointcut" specifikációval, például "naplózza az összes függvényhívást, amikor a függvény neve „set”-tel kezdődik" . Ez lehetővé tesz olyan viselkedések hozzáadását a programhoz, amelyek nem játszanak központi szerepet az üzleti logikában, (mint például a naplózás), anélkül, hogy a funkcionalitás kódmagját összezavarná.

Az AOP magában foglalja a programozási módszereket és eszközöket, amelyek támogatják az problémák modulálását a forráskód szintjén, míg az aspektus-orientált szoftverfejlesztés egy egész mérnöki tudományágra utal.

Az aspektus-orientált programozás magában foglalja a program logikájának különálló részekre bontását (úgynevezett aggodalmak, kohéziós területek). Szinte minden programozási paradigma támogatja az aggodalmak bizonyos szintű csoportosítását és beágyazását különálló, független entitásokba azáltal, hogy absztrakciókat (pl. függvények, eljárások, modulok, osztályok, metódusok) biztosít, amelyek felhasználhatók ezeknek az aggodalmaknak a megvalósítására. Egyes aggodalmak több absztrakciót „átvágnak” egy programban, és dacolnak a megvalósítás ezen formáival. Ezeket az aggályokat átfogó, vagy horizontális aggályoknak nevezzük.

A naplózás egy átfogó problémára ad megoldást, mivel ez a stratégia szükségszerűen érinti a rendszer minden naplózott részét. A naplózás ezáltal átvágja az összes naplózott osztályt és metódust.

Minden AOP-implementáció rendelkezik néhány átfogó kifejezéssel, amelyek minden aggályt összefoglalnak. Az implementációk közötti különbség a rendelkezésre álló konstrukciók teljesítményében, biztonságában és használhatóságában rejlik. Például az elfogók, amelyek specifikálják a metódusokat a keresztmetszetek korlátozott formáinak kifejezésére, anélkül, hogy nagyban támogatnák a típusbiztonságot vagy a hibakeresést. Az AspectJ számos ilyen kifejezést tartalmaz, és egy speciális osztályba, egy aspektusba foglalja őket. Például egy aspektus megváltoztathatja az alapkód viselkedését (a program nem aspektusú része) azáltal, hogy tanácsokat (további viselkedéseket) alkalmaz különböző csatlakozási pontokon (a programban lévő pontokon), amelyeket egy pontkivágásnak nevezett számszerűsítés által, vagy lekérdezésben határoznak meg (amely észleli, hogy egy adott csatlakozási pont egyezik-e). Egy aspektus binárisan kompatibilis szerkezeti változások végrehajtására is képes más osztályokban, például további tagok vagy szülők hozzáadásával.

Története Az AOP-nak számos közvetlen elődje van – A1 és A2: reflexiós és metaobjektum protokollok, tárgyorientált programozás, kompozíciószűrés és adaptív programozás . "Adaptive Object Oriented Programming: The Demeter Approach with Propagation Patterns" Karl Liebherr 1996 presents a well-worked version of essentially the same thing (Lieberherr subsequently recognized this and reframed his approach).

Gregor Kiczales és munkatársai a Xerox PARC-nél kidolgozták az AOP explicit koncepcióját, és ezt követték az AspectJ AOP Java-bővítményével. Az IBM kutatócsoportja a nyelvi tervezési megközelítés helyett eszközszemléletű megközelítést követett, és 2001-ben javasolta a Hyper/J-t és a Concern Manipulation Environment-t, amelyek nem terjedtek el széles körben.

A Microsoft Transaction Server az AOP első jelentős alkalmazása, amelyet az Enterprise JavaBeans követ.

Motiváció és alapfogalmak Jellemzően, ha egy aspektus szétszórt vagy szövevényes, mint a kód, megnehezíti annak megértését és fenntartását. A funkció (például a naplózás) miatt szétszórva van számos függvény között, amelyek használhatják a funkcióját, esetleg teljesen független rendszerekben is, különböző forrásnyelveken…stb. Ez azt jelenti, hogy a naplózás megváltoztatásához szükség lehet az összes érintett modul módosítására. Az aspektusok nemcsak a kifejeződésükre utaló rendszerek fő funkciójával, hanem egymással is összekuszálódnak. Ez azt jelenti, hogy egy aggály megváltoztatása magában foglalja az összes kusza aggály megértését, vagy valamilyen eszközt, amellyel a változások hatása következtetni lehet.

Vegyünk például egy banki alkalmazást, amely elvileg nagyon egyszerű módszerrel utal át összeget egyik számláról a másikra: Note: The examples in this article appear in a syntax that resembles that of the Java language.void transfer(Account fromAcc, Account toAcc, int amount) throws Exception { if (fromAcc.getBalance() < amount) throw new InsufficientFundsException();

fromAcc.withdraw(amount); toAcc.deposit(amount); }Ez az átviteli módszer azonban figyelmen kívül hagy bizonyos szempontokat, amelyeket egy telepített alkalmazásnak meg kell követelnie: hiányoznak a biztonsági ellenőrzések annak ellenőrzésére, hogy az aktuális felhasználó rendelkezik-e jogosultsággal a művelet végrehajtására; az adatbázis-tranzakciónak magába kell foglalnia a műveletet a véletlen adatvesztés megelőzése érdekében; diagnosztikához a műveletet naplózni kell a rendszernaplóba...stb.

A példa kedvéért egy változat, amely az összes fentebb említett aggályt tartalmazza, valahogy így nézhet ki:void transfer(Account fromAcc, Account toAcc, int amount, User user, Logger logger, Database database) throws Exception { logger.info("Transferring money...");

if (!isUserAuthorised(user, fromAcc)) { logger.info("User has no permission."); throw new UnauthorisedUserException();

if (fromAcc.getBalance() < amount) { logger.info("Insufficient funds."); throw new InsufficientFundsException();

fromAcc.withdraw(amount); toAcc.deposit(amount);

database.commitChanges(); // Atomic operation.

logger.info("Transaction successful."); }Ebben a példában más érdekek is összekeveredtek az alapvető funkciókkal (ezt néha üzleti logikai aggálynak is nevezik). A tranzakciók, a biztonság és a naplózás mind átfogó aggályokat példáznak.

Most nézzük meg, mi történne, ha hirtelen meg kellene változtatnunk (például) az alkalmazás biztonsági szempontjait. A program jelenlegi verziójában a biztonsággal kapcsolatos műveletek számos metódusban elszórtan jelennek meg, és egy ilyen változtatás komoly erőfeszítést igényel.

Az AOP megpróbálja megoldani ezt a problémát azáltal, hogy lehetővé teszi a programozó számára, hogy horizontális aggályait kifejezhesse önálló modulokban, amelyeket aspektusoknak nevezünk. Az aspektusok tanácsokat (a program meghatározott pontjaihoz kapcsolt kód), és típusközi deklarációkat (más osztályokhoz hozzáadott strukturális tagok) tartalmazhatnak. Például egy biztonsági modul tartalmazhat tanácsokat, amelyek végrehajtanak egy biztonsági ellenőrzést, mielőtt hozzáférnek a bankszámlához. A pointcut meghatározza azokat az időket (csatlakozási pontokat), amikor valaki hozzáférhet a számlához, a tanácsadó részben található kód pedig a biztonsági ellenőrzés végrehajtásának módját tartalmazza. Ebben az esetben az ellenőrzés és a helyek is egy helyen lesznek. Továbbá, egy jó pointcut előre jelezheti a későbbi programváltozásokat, így ha egy másik fejlesztő új metódust hoz létre, hogy hozzáférhessen a bankszámlához, akkor a tanács az új metódusra hivatkozik, amikor végrehajtja.

Tehát a fenti példa alapján a naplózás megvalósítására egy aspektusban így nézne ki:aspect Logger { void Bank.transfer(Account fromAcc, Account toAcc, int amount, User user, Logger logger) { logger.info("Transferring money...");

void Bank.getMoneyBack(User user, int transactionId, Logger logger) { logger.info("User requested money back.");

// Other crosscutting code. }Gondolhatunk az AOP-ra, mint hibakereső eszköz, vagy felhasználói szintű eszköz. Tanácsot kell fenntartani azokra az esetekre, amikor nincs lehetőségünk megváltoztatni a funkciót (felhasználói szint), vagy nem szeretnénk megváltoztatni a funkciót a gyártási kódban (hibakeresés).

Csatlakozás pont modellek Az aspektus-orientált nyelv tanácsokkal kapcsolatos komponense egy csatlakozási pont modellt (JPM) határoz meg.

A JPM három dolgot határoz meg:

Amikor a tanács képes lefutni. Ezeket csatlakozási pontnak nevezik, mert ezek pontok egy futó programban, ahol össze lehet kapcsolni különböző hasznos viselkedéseket. A csatlakozási pontoknak megszokottnak és érthetőnek kell lenniük, hogy egy hétköznapi programozó számára is hasznos legyen. Stabilnak kell lennie a lényegtelen programmódosítások során is, hogy az aspektus is stabil maradjon az ilyen változtatások alatt. Sok AOP implementáció támogatja a metódusok végrehajtását és a mezőre történő hivatkozásokat, mint csatlakozási pontok. A csatlakozási pontok (pontvágások) megadásának (vagy számszerűsítésének) módja. A pontvágások határozzák meg, hogy vajon a megadott csatlakozási pontok megegyeznek-e. A legtöbb hasznos pointcut nyelv az alapnyelvhez hasonló szintaxist használ (pl. az AspectJ Java aláírásokat használ), és lehetővé teszi az újrafelhasználást elnevezéssel és kombinációval. Egy csatlakozási ponton futtatandó kód megadásának eszköze. Az ApectJs hívja ezt a tanácsot, és képes futtatni a csatlakozási pontok előtt, után és körülöttük. Egyes implementációk olyan dolgokat is támogatnak, mint például egy metódus definiálása egy aspektusban, vagy egy másik osztályban.

A csatlakozási pontok modelljei összehasonlíthatóak az alapján, hogy hogyan lett megadva a módjuk, a pontokon engedélyezett műveletek által, és a szerkezeti fejlesztések alapján.

Az AspectJ csatlakozási pont modellje

Az AspectJs csatlakozási pontja magában foglalja egy metódus vagy konstruktor hívását, végrehajtását, egy osztály vagy objektum inicializálását, egy mező olvasási és írási hozzáférését, kivételkezelést…stb. Nem tartalmazzák a ciklusokat, szuperhívásokat, a dobási záradékokat, többszöri utasításokat. A pontvágásokat a primitív pontvágás kijelölők (PCD) kombinációi határozzák meg. A fajlagos PCD-k egy bizonyos típusi csatlakozási ponthoz illeszkednek (pl. metódus végrehajtás), és általában Java-szerű aláírást tekintenek bemenetként. Az egyik ilyen pontvágás így néz ki: execution(* set*(*)) Ez a pontvágás megegyezik egy metódus-végrehajtás csatlakozási ponttal, ha a metódus „set”-tel kezdődik, és pontosan egy, de bármilyen típusú argumentuma van. A „dinamikus” PCD-k ellenőrzik a futásidejű változókat és a kötési változókat. Például: this(Point) Ez a pontvágás akkor egyezik, ha az éppen végrehajtott objektum a Point osztály egy példánya. Ne feledje, hogy egy osztály minősítetlen neve használható a Java normál típusú keresésén keresztül. A „hatókör” PCD-k korlátozzák az összekapcsolási pont lexikális hatókörét. Például: within(com.company.*) Ez a pontvágás a com.company csomag bármely típusú csatlakozási pontjához illeszkedik. A * a helyettesítő karakterek egyik formája, amellyel sok minden egy aláírással párosítható. A pontvágások összeállíthatók és elnevezhetők újrafelhasználás céljából. Például: pointcut set() : execution(* set*(*) ) && this(Point) && within(com.company.*); Ez a pontmetszet megegyezik egy metódus-végrehajtási csatlakozási ponttal, ha a metódus neve „set”-tel kezdődik, és ez a Point típusú példány a com.company csomagban van. A set() paranccsal hivatkozhatunk rá. ·Az advice (tanács) azt határozza meg, hogy egy csatlakozási ponton (előtt, után, körül) futtasson egy bizonyos kódot (,amely egy metódus kódjához hasonlóan van megadva). Az AOP futtató környezete automatikusan meghívja a Tanácsot, amikor a pontvágás megegyezik a csatlakozási ponttal. Például: after() : set() : { Display.update(); } Ez gyakorlatilag meghatározza: „ha a set() pontvágás megegyezik a csatlakozási ponttal, akkor futtassa a Display.update() kódot, az összekapcsolási pont befejezése után.”

Egyéb lehetséges csatlakozási pont modellek