AspectJ: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
mNessun oggetto della modifica |
|||
Riga 1:
{{W|informatica|luglio 2008}}
'''AspectJ''' è un linguaggio basato su [[Java (linguaggio)|Java]] per aggiungere a Java stesso i cosiddetti ''aspetti''. È uno dei modi utilizzati, in ambito Java, per avvalersi dell'
==Concetti base==
===Join point e pointcut===
Un concetto basilare di '''AspectJ''' è quello di join point. Un join point può essere intuitivamente definito come un certo istante nell'esecuzione del programma; ogni chiamata a un qualsiasi metodo di un oggetto qualunque potrebbe essere un join point, così come leggere il valore di una variabile, creare un oggetto o modificare il valore di una variabile.
I ''pointcut'' invece descrivono le situazioni particolari che si vengono a creare durante l'esecuzione del programma. Un pointcut è cioè una sorta di [[variabile booleana]] il cui valore dipende da una certo insieme di join point, che in un dato momento dell'
È possibile definire un pointcut in maniera estremamente dettagliata; si può ad esempio definire un pointcut che sia valido quando un qualsiasi metodo della [[Classe (informatica)|classe]] A viene chiamato, o ancora, definire un pointcut che è valido quando un metodo di un oggetto di classe A chiama il [[metodo]] xyz(int a, int b) di un oggetto di classe B, oppure un pointcut che sia valido quando viene eseguito il metodo B.exec(String s) tranne nel caso in cui il suddetto metodo venga chiamato da un membro della classe F. È anche possibile definire un pointcut che sia valido quando uno qualunque di un certo insieme di
Un pointcut può
===Advice===
Gli advice sono degli insiemi di istruzioni che vengono eseguite quando un certo pointcut diventa valido. è importante notare che un advice può contenere esso stesso la definizione del pointcut che lo attiva. Un advice nella sua esecuzione può accedere ad eventuali informazioni sui join point che lo compongono che il pointcut può fornirgli. Sempre con riferimento alla metafora del teatro, gli advice definiscono cosa fanno gli spettatori sul palcoscenico.▼
▲quando un certo pointcut diventa valido. è importante notare che un advice può contenere esso stesso la definizione del pointcut che lo attiva. Un advice nella sua esecuzione può accedere ad eventuali
===Aspect===
Le unità elementari dell'
Un aspetto normalmente contiene uno o più pointcut e uno o più advice, oltre a metodi e attributi, come le normali classi. Un aspetto modella una certa 'problematica trasversale' (cioè comune a più oggetti) del
▲Le unità elementari dell' OOP sono gli oggetti, raggruppati in classi; le unità fondamentali dell'AOP sono gli aspetti.
▲Un aspetto normalmente contiene uno o più pointcut e uno o più advice, oltre a metodi e attributi, come le normali classi. Un aspetto modella una certa 'problematica trasversale' (cioè comune a più oggetti) del problema da risolvere; per esempio, poniamo di dover effettuare uno stesso controllo sui valori di input su più metodi appartenenti a classi differenti. Supponendo che tali oggetti non siano legati tra loro da relazioni di ereditarietà, nell'OOP si dovrebbe implementare tale controllo in ogni classe; nell'AOP è invece sufficiente implementare un unico aspetto che abbia un pointcut definito come un OR logico tra un insieme di join point che corrispondono all' esecuzione dei metodi che ci interessano, che contenga al suo interno un advice che restituisca un errore se gli argomenti del metodo eccedono i valori prefissati.
===AspectJ in dettaglio===
====Join points====
Un join point può essere, ad esempio, la chiamata di un metodo; in AspectJ, un join point che viene attivato dalla chiamata del metodo void faiqualcosa(int a), si scrive come:
Riga 76 ⟶ 67:
definisce invece un insieme di join point corrispondenti alla chiamata dei metodi di nome doSomething che siano stati dichiarati come pubblici, che differiscono tra loro per il numero e il tipo degli argomenti; inoltre, i suddetti metodi sono diversi anche per il tipo di dato che ritornano, che può anche essere nullo (esempio: void doSomething(..) ).<br />
Un altro esempio di espressione che codifica una proprietà definente un insieme di join point è il seguente
call(void A.*(..))
Riga 83 ⟶ 74:
====''Pointcut''====
Un pointcut è un join point, oppure una intersezione o una unione tra join point
▲Un pointcut è un join point, oppure una intersezione o una unione tra join point , o più informalmente, una certa situazione che si viene a creare durante l'esecuzione del programma . Un pointcut nella sua definizione comprende uno o più join point : un semplice esempio di pointcut definito a partire da un unico join point è il seguente :
pointcut pc() : call(void doSomething(int))
I pointcut possono inoltre rendere accessibili al codice presente negli advice che vi fanno riferimento alcuni dati presi dai join point che fanno parte della loro definizione
pointcut pc(int i): call (void doSomething(int)) && args(i)
mette a disposizione dell'advice una variabile int i che sarà inizializzata al valore del parametro intero passato al metodo void doSomething(int n). Vale la pena notare che il pointcut definito qui sopra è formalmente una intersezione, ossia un and logico tra due insiemi di join point definiti dalle due espressioni call (void doSomething(int)) e args( int i): quest'ultima espressione indica tutti i join point che accettano come input un unico parametro di tipo int
▲i join point che accettano come input un unico parametro di tipo int . Facendo riferimento a pointcut che nelle loro definizioni hanno, tra gli altri, anche dei join point di tipo call , è possibile che essi indichino all' advice l'oggetto che effettua la chiamata e quello che la riceve. Prendiamo ad esempio il pointcut wait, così definito :
pointcut wait(A1 ac, B2 bd) : call(void wait()) && this(ac) && target(bd)
esso corrisponde a un oggetto appartenente alla classe A1 che, nel suo codice, effettui una chiamata di un metodo void wait() di un oggetto appartenente alla classe B2
pointcut pt() : call(void calcola()) || execution(int moltiplica(int,int))
Riga 106 ⟶ 93:
Tale pointcut coincide sia con la chiamata del metodo void calcola(), sia con l'esecuzione del corpo del metodo int moltiplica(int a, int b)
è anche possibile usare la negazione nella definizione di un pointcut
pointcut wait2(A1 ac, B2 bd) : call(void wait()) && !this(ac) && target(bd)
questo pointcut verrà attivato da una chiamata
In generale, un pointcut
pointcut ct() : call(void sum()) ;
pointcut fl() : cflow(ct) ;
il pointucut fl individua l'insieme di join point generati nell'esecuzione del metodo void sum, oltre al join point generato dalla chiamata del metodo sum()
pointcut fl2() : cflowbelow(ct) ;
questo pointcut fl2 corrisponderà all'insieme dei join point generati nell'esecuzione di void sum, ma non al join point generato dalla chiamata di void sum. il pointcut fl2 non contiene al suo interno il pointcut ct. cflow e cflowbelow sono due parole chiave usate frequentemente per definire pointcut che sono intersezioni di altri pointcut, ossia pointcut che usano nella loro definizione l'AND logico.
▲ad esempio :
pointcut restart() : cflowbelow(execution(void wait()))) && call(void resume(int)) ;
In questo caso, dall'
Con
pointcut pi() : within(java.sql.*);
denota l'
pointcut pi2() : withincode(void insert(Object o));
====Advice====
Gli advice sono degli insiemi di istruzioni che vengono eseguiti prima, dopo oppure al posto di alcuni pointcut. In questo
▲Gli advice sono degli insiemi di istruzioni che vengono eseguiti prima, dopo oppure al posto di alcuni pointcut. In questo testo vengono trattati i primi due casi, visto che la semantica del terzo (advice di tipo 'around' ) è ancora in corso di definizione. Gli advice che vengono eseguiti prima che un pointcut diventi valido sono definiti dalla parola chiave before : prendiamo ad esempio il seguente codice :
Riga 150 ⟶ 135:
questo frammento di codice fa sì che prima
Un advice può anche essere eseguito dopo un certo pointcut :
Riga 158 ⟶ 141:
}
l'
Un advice può definire esso stesso il pointcut da cui dipende
after(): execution (void faQualcosa(..)) {tem.out.println(
}
e tale codice è
Il codice di un advice hanno inoltre accesso alle variabili che il pointcut mette a loro disposizione
pointcut wait(A1 ac, B2 bd) : call(void wait()) && this(ac) && target(bd)
si può scrivere il seguente advice
before (A1 ac , B2 bd ) : wait(ac,bd) {
Riga 176 ⟶ 159:
}
Bisogna ricordare che in java un metodo può terminare regolarmente oppure lanciando un'eccezione
Si veda il seguente codice
after() returning punto1() : { System.out.println("tutto regolare");
}
questo advice verrà eseguito solo se l'esecuzione
after() throwing: punto1() {System.out.println("è stata creata un'eccezione");
Riga 196 ⟶ 179:
}
analogamente, nel caso
after (Exception e ) throwing : call(int moltiplica(int,int)) {
Riga 203 ⟶ 186:
====Aspetti====
Un aspetto modella una problematica trasversale dell'
▲Un aspetto modella una problematica trasversale dell' applicazione. Può contenere al suo interno definizioni di pointcut, advice, attributi e metodi, implementare un'interfaccia od estendere una classe; il viceversa ovviamente non vale.
Esistono aspetti astratti e aspetti concreti, esattamente così come esistono classi astratte e classi concrete; però, a differenza dell'OOP, nell'AOP un aspetto concreto non può estendere un altro aspetto concreto, ma solo un aspetto astratto.
Un esempio è il seguente
<pre>
Riga 263 ⟶ 245:
alla riga 2 c'è la
Un aspetto, esattamente come qualsiasi altro oggetto, può avere uno o più costruttori: in questo caso, il costruttore è implementato nelle righe dalla 5 alla 9.
Nella riga 10 e 13 troviamo la definizione di due semplici pointcut, definiti tramite dei join point di tipo execution. Alla riga 16 e alla riga 18 ci sono due advice che vengono eseguiti, rispettivamente, prima e dopo il pointcut definito alla riga 10; nell'aspetto ci sono anche due advice (righe 29 e 31) che vengono eseguiti l'uno prima e l'altro dopo il pointcut definito alla riga 13. Come accade nelle classi, tutti questi advice hanno accesso alle variabili private dell'aspetto (definite nelle righe dalla 2 alla 15).
Riga 278 ⟶ 259:
aspect nomeaspetto perthis(wait(A1 ac, B2 bd)) { }
tale istruzione assicura che, a ogni oggetto ac in esecuzione che generi un pointcut wait, sia associato un aspetto. Per far sì che a ogni oggetto di un certo tipo, poniamo TiPo, sia associato un aspetto, bisognerebbe scrivere:
aspect nomeaspetto perthis(this(TiPo)) { }
Riga 309 ⟶ 288:
====''Inter-Type declarations''====
In aspectj un aspetto può alterare la struttura stessa degli oggetti
▲In aspectj un aspetto può alterare la struttura stessa degli oggetti aggiunngendo ad essi metodi, attributi e costruttori oltre a quelli che già possiede. Bisogna però fare attenzione a non creare conflitti: i metodi, i costruttori e gli attributi che un aspetto aggiunge ad un oggetto non devono sovrapporsi a metodi, costruttori e attributi che l'oggetto già ha. In parole povere, un aspetto può aggiungere dei metodi, degli attributi o dei costruttori, purché non siano già definiti dall'oggetto stesso.
La sintassi delle inter-type declarations è molto semplice: la dichiarazione
public int Game.time;
aggiunge un attributo di tipo intero e di nome '
private String Ship.name;
aggiunge un attributo di tipo stringa name alla classe Ship. È importante notare che questo attributo è stato dichiarato come privato dall'aspetto, e quindi questo attributo sarà visibile solo dai metodi e dagli advice dell'aspetto, ma non dai metodi della classe Ship.
Riga 322 ⟶ 300:
}
Questa istruzione aggiunge alla classe Game un metodo score() pubblico
public Game.new(String s ) {
Riga 332 ⟶ 310:
== Collegamenti esterni ==
*[http://www.eclipse.org/aspectj/ Home page progetto AspectJ]
[[categoria:Linguaggi di programmazione]]
|