Uso dei proxy in Spring AOP

Sto leggendo un libro, che parla del supporto di AspectJ in Spring AOP.

Di seguito è riportato un paragrafo tratto dal libro:

Per abilitare il supporto delle annotazioni AspectJ nel contenitore IoC di spring, è sufficiente definire un elemento XML vuoto aop: aspectj-autoproxy nel file di configurazione del bean. Quindi, Spring creerà automaticamente proxy per i tuoi bean che corrispondono ai tuoi aspetti AspectJ.

Per i casi in cui le interfacce non sono disponibili o non sono utilizzate nella progettazione di un’applicazione, è ansible creare proxy facendo affidamento su CGLIB. Per abilitare CGLIB, è necessario impostare l’attributo proxy-targetclass = true in aop: aspectj-autoproxy.

Non sono in grado di ottenere il secondo paragrafo. Cosa si intende per ” interfacce non disponibili “. Qualcuno può illustrarlo con un esempio?

Spring AOP utilizza i proxy dinamici JDK o CGLIB per creare i proxy per gli oggetti di destinazione.

Secondo la documentazione di Spring, nel caso in cui il target implementasse almeno un’interfaccia, verrà utilizzato un proxy dinamico JDK. Tuttavia se l’object di destinazione non implementa alcuna interfaccia, verrà creato un proxy CGLIB.

Ecco come puoi forzare la creazione dei proxy CGLIB (imposta proxy-target-class = ” true “):

   

Quando si utilizza AspectJ e il relativo supporto per l’autopossibilità, è ansible forzare anche i proxy CGLIB. È qui che viene utilizzato e anche qui “proxy-target-class” deve essere impostato su true :

  

Si prega di fare riferimento alla sezione Meccanismi di Proxying di Aspect Oriented Programming con la documentazione Spring per maggiori dettagli.

Spring preferisce utilizzare le interfacce per AOP perché può utilizzare i proxy JDK.

Ad esempio, ho un’interfaccia MyService

 public interface MyService { void doSomething(); } 

E un’implementazione MyServiceImpl

 @Service public class MyServiceImpl implements MyService { public void doSomething() { // does something! } } 

Se Spring scopre di aver configurato aspetti per MyService , creerà un proxy JDK che implementa MyService e quindi MyService proxy di tutte le chiamate attraverso il bean MyServiceImpl , aggiungendo funzionalità di aspetto laddove appropriato.

I proxy JDK funzionano implementando la stessa interfaccia dell’object target e delegando le chiamate ad esso; non funzionano se non c’è un’interfaccia da implementare. Nel caso in cui non si disponga di un’interfaccia come sopra, Spring ha bisogno di utilizzare una libreria di codici byte come CGLIB per creare dynamicmente classi in runtime che incorporino le funzionalità dell’aspetto.

Ho trovato un blog qui che spiega chiaramente come AOP, Caching e Transaction funziona utilizzando le classi proxy di runtime.

Quando non si codifica per interfacciare (citando dalla sezione del blog ‘ Cosa succede se la class bean non implementa alcuna interfaccia? ‘): –

Per impostazione predefinita, se il bean non implementa un’interfaccia, Spring utilizza l’ereditarietà tecnica: all’avvio viene creata una nuova class. Si eredita dalla class bean e aggiunge un comportamento nei metodi figlio. Per generare tali proxy, Spring utilizza una libreria di terze parti chiamata cglib.

Spring AOP fa un uso estensivo dei proxy come meccanismo per implementare preoccupazioni trasversali (ovvero aspetti) in modo non intrusivo, l’idea fondamentalmente è usare i proxy come wrapper che arricchiscono il comportamento originale, ovvero aggiungono capacità transazionali.

Per ottenere questo ci sono due opzioni, a seconda che l’object originale implementa o meno un’interfaccia.

Nel primo caso (l’object originale implementa almeno un’interfaccia) le funzionalità di proxy dinamico dell’API di reflection vengono utilizzate per creare un object proxy che IMPLEMENTS le stesse interfacce che l’object originale e quindi il proxy possono invece essere utilizzati.

Nel secondo caso (l’object originale NON implementa alcuna interfaccia), quindi deve essere usato un trucco più elaborato, e questo è quando appare CGLIB. Secondo la pagina del progetto “CGLIB viene utilizzato per estendere le classi Java e implementare interfacce in fase di esecuzione”. Quindi in questo caso il trucco consiste nel creare un proxy che ESTENDE l’object originale e che quindi possa essere usato al suo posto.