1 aop sandro pedrazzini approfondimento aspect oriented programming (aop)

44
1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

Upload: nunziatina-fiorini

Post on 02-May-2015

257 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

1 AOP

Sandro Pedrazzini

Approfondimento

Aspect Oriented Programming (AOP)

Page 2: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

2 AOP

Sandro Pedrazzini

Aspect Oriented Programming

• Paradigma di programmazione, che prevede l’inserimento di funzionalità comune (cross-cutting concerns) a funzionalità esistente

• Lo scopo è quello di separare aspetti comuni (logging, security, gestione eccezioni, ecc.) da business logic nel senso più stretto

Page 3: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

3 AOP

Sandro Pedrazzini

Aspect Oriented Programming (AOP)

• Tutti i paradigmi, in particolare il paradigma a oggetti, prevedono l’incapsolamento di funzionalità in entità separate, creando astrazioni (metodi, classi).

• Esistono però funzionalità che potrebbero non rientrare facilmente in un’organizzazione di questo tipo, perché più trasversali (cross-cutting)

• Esempio: logging

Page 4: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

4 AOP

Sandro Pedrazzini

Cross-cutting concerns tipici

• Sincronizzazione• Gestione della memoria• Persistenza• Security• Caching• Logging• Monitoring• Business rules• …

Page 5: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

5 AOP

Sandro Pedrazzini

Implementazioni

• Le implementazini più diffuse per Java sono AspectJ e Hyper/J

• AOP viene integrata in diversi framework, soprattutto attraverso l’implementazione di AspectJ

– Spring– JBoss AOP– Guice

Page 6: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

6 AOP

Sandro Pedrazzini

Terminologia di base

• Cross-cutting concern

Funzionalità comune (trasversale) da condividere tra più funzioni. Esempio: funzionalità di logging, identica, all’interno di metodi o classi diverse, in cui, ad esempio, un log dev’essere eseguito in entrata e uno in uscita.

• Advice

Codice aggiuntivo da applicare al modello di business esistente. Esempio: codice di logging, unico, da chiamare separatamente quando necessario.

Page 7: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

7 AOP

Sandro Pedrazzini

Terminologia di base (2)

• Pointcut

Punto di esecuzione all’interno dell’applicazione. Punto in cui un cross-cutting concern dev’essere applicato.

Esempio: punto raggiunto quando un certo metodo inizia (logging di entrata) o termina (logging di chiusura)

• Aspect

Modulo che combina la descrizione del pointcut (join-point) e il body dell’advice.

Esempio: aggiungiamo un aspect all’applicazione, specificando modalità di logging e quando questa va eseguita

Page 8: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

8 AOP

Sandro Pedrazzini

Logging

• Tipicamente una funzionalità da aspect come logging la si trova in più parti nel codice, rendendo difficoltosa la sua comprensione e la sua manutenzione

• Una modifica al logging può significare modificare diversi moduli, classi e metodi

Page 9: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

9 AOP

Sandro Pedrazzini

Logging (2)

• Codice in ogni modulo

Page 10: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

10 AOP

Sandro Pedrazzini

Logging (3)

• Centralizzazione in un unico aspect

Page 11: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

11 AOP

Sandro Pedrazzini

Esempio

• Funzionalità di pagamento con carta di credito

public class BillingService implements IBillingService { …

public Receipt chargeOrder(Order order, CreditCard card) throws Exception { ChargeResult result= fCreditCardProcessor.process(order.getAmount(), card); return ...;

}}

Page 12: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

12 AOP

Sandro Pedrazzini

Esempio (2)

• Abbiamo però anche bisogno di controlli di security e logging

public Receipt chargeOrder(User user, Order order, CreditCard card) throws Exception { logger.info(“Inizio pagamento…”);

if (!checkUserPermission(user) { logger.info(“Utente non autorizzato…”); throw new UnauthorizeException(); }

ChargeResult result= fCreditCardProcessor.process(order.getAmount(), card);

logger.info(“Fine pagamento…”); return ...;

}

Page 13: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

13 AOP

Sandro Pedrazzini

Esempio (3)

• Nel codice precedente, elementi di logging e di security sono da considerare cross-cutting concerns

• Cosa succede se dobbiamo modificare elementi di security nell’applicazione? Siccome questi elementi sono sparsi in tutta l’applicazione, le modifiche saranno parecchie.

• Meglio sarebbe poterli gestire in modo centrale

Page 14: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

14 AOP

Sandro Pedrazzini

Aspect

• AOP spinge a risolvere il problema della presenza di singoli elementi in più parti del codice permettendo di esprimere questi cross-cutting concerns attraverso moduli chiamati aspects

• Un aspect contiene advice (codice da eseguire) e pointcut (dichiarazione di quando gli advice vanno eseguiti)

• Esempio: un aspect potrebbe contenere – codice di verifica della security– specifica che la verifica viene eseguita ogni volta prima della chiamata a charge()

Page 15: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

15 AOP

Sandro Pedrazzini

Aspect (2)

• Possibile esempio in AspectJ “pseudocode”

public aspect SecurityCheck { before() : within(Receipt IBillingService.chargeOrder( User user, Order order, CreditCard card)) && call(ChargeResult ICreditCardProcessor.charge( long, CreditCard)) {

if (!checkUserPermission(user) { logger.info(“Utente non autorizzato…”); throw new UnauthorizeException(); } }

Page 16: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

16 AOP

Sandro Pedrazzini

Aspect (3)

• AspectJ permette tutta una serie di modalità dichiarative per specificare i join points

• I joint point sono l’elemento più critico, perché attraverso la loro dichiarazione, espressa anche attraverso regular expressions, si specifica il match

• Espressioni complesse rendono il codice poco “prevedibile” e quindi anche poco mantenibile

Page 17: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

17 AOP

Sandro Pedrazzini

Esempi di pointcut

• execution(* set*(*))

match con l’esecuzione di tutti i metodi il cui nome inizia con “set” e hanno un unico parametro di qualsiasi tipo

• within(ch.supsi.*)

limita lo scope del pointcut a qualsiasi cosa (classe, metodo) nel package “ch.supsi”

• this(CreditCard)

Questo pointcut risolve quando l’oggetto attuale in esecuzione (this) è un’istanza di CreditCard

• execution(* set*(*)) && within(ch.supsi.*) && this(CreditCard)

Combinazione dei tre criteri precedenti

Page 18: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

18 AOP

Sandro Pedrazzini

Implementazioni

• Esistono fondamentalmente due tipi di implementazione per AOP

– Class-waving

Integra le implementazioni degli aspect direttamente nelle classi in cui devono essere eseguite. Il weaving può essere applicato sia a livello di compilazione, che loading o runtime.

– Proxy

La chiamata al metodo di un oggetto viene intercettata. Vengono usati Java dynamic proxy o CGLIB (code generation lib)I framework che si basano sul proxy sono generalmente più semplici e si basano quasi esclusivamente sul meccanismo di method interceptor.

Page 19: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

19 AOP

Sandro Pedrazzini

Implementazione: proxy (1)

• Viene generata una sottoclasse della classe da estendere, o dinamicamente, a runtime (Java dynamic proxy), oppure modificando il bytecode durante la generazione (CGLIB)

Subject

Proxy

request()...

request()...

RealSubject

request()...

Page 20: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

20 AOP

Sandro Pedrazzini

Implementazione: proxy (2)

• Il meccanismo di Java dynamic proxy può essere applicato solo se esiste un’interfaccia della classe da estendere

• Con CGLIB, invece, il proxy eredita dalla stessa classe che estende

RealSubject

Proxy

request()...

request()...

RealSubject

request()...

Page 21: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

21 AOP

Sandro Pedrazzini

AOP in framework

• Framework come Spring, Guice o altri, integrano le funzionalità di AspectJ, creando se possibile un livello di astrazione

– Spring: ne facilita l’utilizzo, pur lasciando aperta la possibilità di accedere a funzionalità avanzate e specifiche di AspectJ

– Guice: ne facilita e ne delimita l’utilizzo, allo scopo di promuoverne l’impiego dove questo migliora il codice, ma evitarne l’abuso, con conseguenze nefaste nel codice

Page 22: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

22 AOP

Sandro Pedrazzini

AOP con Guice

• Guice prevede AOP attraverso il meccanismo di “method interception”

• In questo modo si può eseguire un advice ogni volta che uno specifico metodo viene invocato

• In Guice si parla di – Matcher: elemento esegue il match => pointcut– MethodInterceptor: parte di codice da eseguire => advice

Page 23: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

23 AOP

Sandro Pedrazzini

AOP con Guice (2)

• Matcher

Dichiarazione che permette di accettare o rifiutare un valore. In Guice servono due matcher: uno per specificare la classe e uno per specificare il metodo.

• MethodInterceptor

Eseguito all’invocazione di un metodo che risolve il match.Riceve informazioni sulla chiamata: il metodo, i suoi argomenti, e l’istanza dell’oggetto invocante.

Page 24: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

24 AOP

Sandro Pedrazzini

Esempio

• Riutilizzare l’esempio del pagamento con carta di credito già usato per DI

• Eseguire durante l’esecuzione del pagamento un controllo attraverso AOP per verificare i giorni in cui può avvenire il pagamento

• Implementato: specificare uno o più giorni in cui il servizio non può essere usato

Page 25: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

25 AOP

Sandro Pedrazzini

Esempio (2)

• Codice attuale

public class BillingService implements IBillingService { …

public Receipt chargeOrder(Order order, CreditCard card) throws Exception { ChargeResult result= fCreditCardProcessor.process(order.getAmount(), card); return ...;

}}

Page 26: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

26 AOP

Sandro Pedrazzini

Matcher

• Definiamo un’annotation per specificare il Matcher. Servirà a segnalare il metodo interessato.

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface NotOnWeekends {}

Page 27: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

27 AOP

Sandro Pedrazzini

Matcher (2)

• Utilizzo dell’annotation

public class BillingService implements IBillingService { …

@NotOnWeekends public Receipt chargeOrder(Order order, CreditCard card) throws Exception { ChargeResult result= fCreditCardProcessor.process(order.getAmount(), card); return ...;

}}

Page 28: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

28 AOP

Sandro Pedrazzini

Interceptor

public class WeekendBlocker implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { Calendar today = new GregorianCalendar(); String todayDisplayName = today.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.ENGLISH); Order order = (Order) invocation.getArguments()[0];

if (todayDisplayName.equals(”Sunday")) { throw new IllegalStateException( invocation.getMethod().getName() + " for " + order.getAmount() + " not allowed on " + todayDisplayName); }

return invocation.proceed(); }}

Page 29: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

29 AOP

Sandro Pedrazzini

Interceptor (2)

• Chiamata al metodo vero e proprio

invocation.proceed();

• Accesso ai parametri

invocation.getArguments()

• Accesso alle informazioni del metodo

invocation.getMethod()

Page 30: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

30 AOP

Sandro Pedrazzini

Modulo di bind

• Guice utilizza un modulo per specificare i vari binding

public class NotOnWeekendsModule extends AbstractModule { protected void configure() { bindInterceptor(Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class), new WeekendBlocker());

bind(ITransactionLog.class). toProvider(DatabaseTransactionProvider.class); bind(ICreditCardProcessor.class). to(PaypalCreditCardProcessor.class);

bind(IBillingService.class).to(BillingService.class); }}

Page 31: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

31 AOP

Sandro Pedrazzini

Modulo di bind (2)

bindInterceptor(

Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class),

new WeekendBlocker());

Match con ogni classe

Solo i metodi con questa annotation

Oggetto contenente il metodo interceptor

Page 32: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

32 AOP

Sandro Pedrazzini

Main

public class Main{ public static void main(String[] args) { Injector injector = Guice.createInjector(new NotOnWeekendsModule()); …

IBillingService billingService = injector.getInstance(IBillingService.class); … }}

Page 33: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

33 AOP

Sandro Pedrazzini

Esempio 2: security

• Controllo se un certo utente cerca di eseguire una determinata azione e se ha il diritto di farlo

• Le azioni che un utente può eseguire vengono specificate seguendo un approccio che utilizza ruoli

• Specifichiamo con annotation quali ruoli hanno diritto ad eseguire una determinata azione

Page 34: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

34 AOP

Sandro Pedrazzini

Esempio 2: security (2)

• Un interceptor viene creato per verificare se l’utente che chiama l’azione ha il ruolo necessario (in un caso reale, ruolo e azione sono legati con permission, perciò andrebbero verificate anche queste)

• User manager che mantiene le informazioni sull’utente registrato:

public interface IUserManager { void setCurrentUser(User user); User getCurrentUser();}

Page 35: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

35 AOP

Sandro Pedrazzini

User Manager

• All’interno di un’applicazione multiutente lo user manager utilizzerebbe la sessione per gestire gli utenti registrati

• In un’applicazione desktop, invece, basta un singleton

• Lo user possiamo rappresentarlo come una semplice classe che gestisce il nome dell’utente (informazione minima) e un set di ruoli appartenenti all’utente

Page 36: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

36 AOP

Sandro Pedrazzini

User

public class User {

private String fName; private Set<Role> fRoles;

public User(String name, Set<Role> roles) { fName = name; fRoles = roles; }

public String getName() { return fName; }

public Set<Role> getRoles() { return fRoles; } …}

Page 37: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

37 AOP

Sandro Pedrazzini

Ruoli

• Per specificare ruoli in modo semplice e controllato, usiamo una enumeration

public enum Role { CUSTOMER, EMPLOYEE}

Page 38: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

38 AOP

Sandro Pedrazzini

Annotazione delle azioni

• Le annotation ci permettono di segnalare quali ruoli sono richiesti per eseguire una certa operazione

• Usata per segnalare un metodo e accessibile a runtime

• value() serve a specificare il ruolo necessario

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RequiresRole {

Role value();}

Page 39: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

39 AOP

Sandro Pedrazzini

Azioni

• Supponendo ora di avere una classe con delle azioni da eseguire, le annotation ci permettono di specificare con quale ruolo

public class VideoRental {

@RequiresRole(Role.CUSTOMER) ...

@RequiresRole(Role.EMPLOYEE) …}

Page 40: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

40 AOP

Sandro Pedrazzini

Azioni (2)

public class VideoRental {

@Inject IUserManager fUserManager;

@RequiresRole(Role.CUSTOMER) public void rentMovie(long movieId) { System.out.println(String.format( "Movie %d rented by user %s.”, movieId, fUserManager.getCurrentUser())); }

@RequiresRole(Role.EMPLOYEE) public void registerNewMovie(String name) { System.out.println(String.format( "New movie \"%s\" registered by user %s.", name, fUserManager.getCurrentUser())); }}

Page 41: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

41 AOP

Sandro Pedrazzini

Interceptor• A questo punto ci vuole un interceptor che faccia uso delle

informazioni specificate dalle annotation per verificare i ruoli

public class RoleValidationInterceptor implements MethodInterceptor {

@Inject private IUserManager fUserMgr;

public Object invoke(MethodInvocation invocation) throws Throwable {

Role requiredRole = invocation.getMethod().getAnnotation(RequiresRole.class).value();

if (fUserMgr.getCurrentUser() == null || !fUserMgr.getCurrentUser().getRoles().contains(requiredRole)){

throw new IllegalStateException(”…”); }

return invocation.proceed(); }}

Page 42: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

42 AOP

Sandro Pedrazzini

Module• Bisogna inoltre specificare quando viene usato l’interceptor

public class ExampleModule extends AbstractModule { public void configure() { bind(IUserManager.class).to(UserManager.class).in(Scopes.SINGLETON); RoleValidationInterceptor roleValidationInterceptor = new RoleValidationInterceptor(); bindInterceptor(any(), annotatedWith(RequiresRole.class), roleValidationInterceptor);

//necessario, per risolvere @Inject in rileValidationInterceptor requestInjection(roleValidationInterceptor); }}

Page 43: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

43 AOP

Sandro Pedrazzini

Module (2)

• Prima di tutto associamo un’implementazione di IUserManager all’interfaccia. Definendola come singleton, specifichiamo che lo stesso oggetto usato in VideoRental venga usato anche in RoleValidationInterceptor

• In seguito associamo l’interceptor a tutti i metodi annotati con RequiresRole

• L’ultimo passaggio è necessario per iniettare nell’interceptor le sue dipendenze (nel nostro caso con UserManager)

Page 44: 1 AOP Sandro Pedrazzini Approfondimento Aspect Oriented Programming (AOP)

44 AOP

Sandro Pedrazzini

Creazione di un framework AOP