Invest in people before investing in tools

Il blog di Matteo Baglini
posts - 118, comments - 95, trackbacks - 697

[Spring.NET #32] Spring.Aop, Pointcut e Advisor

Un Pointcut definisce una regola di individuazione di un Joinpoint. Spring.NET offre diverse implementazioni di Pointcut, forniti come moduli indipendendi, implementati come singole entità in modo da renderli riutilizzabili ed intersecabili per diversi Advice.

Ogni Pointcut implementa l'interfaccia IPointcut, la quale tramite i due membri ITypeFilter e IMethodMatcher permette di filtrare in base al tipo ed alla firma del metodo. Nella maggior parte dei casi le implementazioni dei Pointcut sono gestite in maniera statica (StaticPointcut), in modo da effettuare il caching del risultato di una valutazione di matching (operazione costosa in termini di performance) la prima volta che viene eseguita, questo permette di velocizzare la procedura di Weaving. Esiste un tipo di Pointcut non "cachabile", il DynamicPointcut, il quale effettua la valutazione di matching non solo in base al tipo ed alla firma del metodo, ma anche in base ai parametri passati al metodo stesso, quindi la valutazione avverrà ad ogni invocazione. Possiamo effettuare una operazione di unione dei Pointcut (verrà eseguito ogni Pointcut per il quale la valutazione di matching risulta vera), oppure una operazione di intersezione (verrà eseguito ogni Pointcut solo se la valutazione di matching risulta vera per tutti).

Spring.NET fornisce built-in i seguenti Pointcut:

  • Regular Expression: è un generico Regular Expression Pointcut, il quale permette di definire una lista di pattern da applicare per il matching. Perchè la valutazione del Pointcut sia vera devono "matchare" tutti i pattern. Questo Pointcut è di tipo statico.
  • Attribute: permette di effettuare il matching di un metodo marcato con un determinato Attribute. Anche questo Pointcut è di tipo statico.
  • Control Flow: permette di effettuare il matching di un metodo in base al suo StackTrace. Per esempio possiamo indicare di applicare un Advice ad un metodo A solo se esso è stato chiamato da B. Questo Pointcut è di tipo dinamico, quindi molto costoso, in termini di performance. In più questo Pointcut richiede un po di attenzione perchè può incontrare dei problemi che la funzionalità di Method Inlining del Jit Compiler applicato quando generiamo un assembly in Release mode. Per evitare problemi ci sono una serie di tecniche mostrate qui: Dynamic Pointcuts

Per implementare un nostro Pointcut baterà creare una classe che implementa l'interfaccia IPointcut oppure ereditare dalla classe base StaticMethodMatcherPointcut, la quale ci permette di risparmiare un po di codice di plumbing.

L'unione di Pointcut e Advice si chiama Advisor, il quale crea di fatto un Aspetto modularizzato e riutilizzabile nella nostra applicazione. Dato che nel file di cofigurazione dobbiamo sempre indicare un Pointcut più una serie di Advice, Spring.NET fornisce una classe Advisor per ogni classe Pointcut (es: RegularExpressionMethodPointcutAdvisor, AttributeMatchMethodPointcutAdvisor) più una classe DefaultPointcutAdvisor in modo da semplificare la configurazione.

Passiamo ad un esempio pratico, supponiamo di avere nel Service Layer una classe TransferService definita così:

   1: public class TransferService : ITransferService
   2: {
   3:     private string _role = String.Empty;
   4:     public string Role
   5:     {
   6:         set { _role = value; }
   7:     }
   8:  
   9:     public void Transfer(Account fromAccount, Account toAccount, int amount)
  10:     {
  11:         IPrincipal _currentPrincipal = Thread.CurrentPrincipal;
  12:         if (!_currentPrincipal.IsInRole(_role))
  13:             throw new SecurityException("The logged user can't perform Transfer Account operation.");
  14:  
  15:         fromAccount.withdraw(amount);
  16:         toAccount.deposit(amount);
  17:     }
  18: }

il nostro obbiettivo è di eliminare il codice di validazione dell'utente da questa classe per inserirlo in un aspetto. In questo post impostiamo solo l'Advisor che intercetterà l'invocazione del metodo, quindi nel file di configurazione inseriamo un NameMatchMethodPointcutAdvisor:

<object id="aroundAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
  <property name="Advice">
  </property>
  <property name="MappedName" value="Transfer" />
</object>

Il NameMatchMethodPointcutAdvisor è una versione semplificata del RegularExpressionMethodPointcutAdvisor, il quale permette di definire un pattern di matching del metodo, che in questo caso è "Transfer".

Print | posted on mercoledì 7 maggio 2008 22:25 | Filed Under [ .NET OpenSource Spring.NET ]

Powered by:
Powered By Subtext Powered By ASP.NET