2011-08-27 26 views
6

Sono abbastanza nuovo per AspectJ e ho un problema che mi ispira se qualche ricerca non riesco a risolvere. Ho il seguente aspetto riguardante una Banca, l'aspetto controlla se il saldo della Banca è valido dopo ogni chiamata al metodo pubblico.Ricorsione con AspectJ

pointcut BankCheck(Bank bank): call(public * Bank.*(..)) && target(bank); 

Object around(Bank bank): BankCheck(bank) { 
    int balance = bank.getTotalBalance(); 
    Object result = proceed(bank); 
    if (balance != bank.getTotalBalance()) { 
     LOGGER.warn("The total balance of the bank is not equal."); 
    } else { 
     LOGGER.info("Ok"); 
    } 
    return result; 
} 

Il problema è che sotto l'aspetto io uso il metodo bank.getTotalBalance(), che è di per sé un metodo banca pubblica. Pertanto l'aspetto è consigliato ogni volta e questo problema di ricorsività continua fino a quando non viene lanciata un'eccezione. C'è un modo per risolvere questo problema, ad esempio disattivando il meccanismo di avviso all'interno dell'aspetto?

risposta

4

Prova questo:

public aspect BankTotalBalanceAspect { 
    pointcut BankCheck(Bank bank): call(public * Bank.*(..)) && target(bank); 

    Object around(Bank bank): BankCheck(bank) && !within(BankTotalBalanceAspect) { 
     int balance = bank.getTotalBalance(); 
     Object result = proceed(bank); 
     if (balance != bank.getTotalBalance()) { 
      LOGGER.warn("The total balance of the bank is not equal."); 
     } else { 
      LOGGER.info("Ok"); 
     } 
     return result; 
    }  
} 
+2

Grazie, questo è esattamente quello che stavo cercando. –

0

Non ho molta familiarità con la sintassi del punto di vista di AspectJ, ma avete un modo per escludere la chiamata getTotalBalance dalla definizione del punto di destinazione? Ciò impedirebbe che la ricorsione si verifichi.

Inoltre, la definizione del punto di destinazione sembra corrispondere in modo troppo ampio: presumo che il controllo del saldo implementato nel tuo aspetto debba essere eseguito per solo per i metodi. Quindi una chiamata di sola lettura come getTotalBalance non dovrebbe essere uguagliata comunque. Hai un modo di distinguere tra metodi di sola lettura e scrittura nella classe target, e. g. da annotazioni di transazione esistenti o qualcosa del genere?

In caso contrario, è possibile che si desideri introdurre tali annotazioni (personalizzate) autonomamente e regolare il punto di collegamento in modo che corrisponda a tutte le chiamate al metodo pubblico che non sono contrassegnate come readonly. Ma questo significherebbe modificare il codice nella classe di destinazione, che non è sempre un'opzione. Ma YMMV.

+0

Sarà infatti possibile fare alcune annotazioni personalizzate e risolvere il problema in questo modo. La soluzione di Insentre @Constantiner è molto più semplice. Grazie comunque –