Spring AOP non funziona per la chiamata di metodo all’interno di un altro metodo

Esistono due metodi definiti in ABC.java

public void method1(){ ......... method2(); ........... } public void method2(){ ............... ............... } 

Voglio avere AOP sulla chiamata di method2 . Così ho creato una class, AOPLogger.java , con funzionalità dell’aspetto fornita in un metodo checkAccess
Nel file di configurazione, ho fatto qualcosa di simile qui sotto

        

Ma quando viene chiamato il mio metodo2, la funzionalità AOP non viene invocata, ovvero il metodo checkAccess non viene richiamato dalla class AOPLogger.

Qualcosa che mi manca?

L’aspetto è applicato a un proxy che circonda il bean. Nota che ogni volta che ottieni un riferimento a un bean, in realtà non è la class a cui fa riferimento la tua configurazione, ma una class sintetica che implementa le interfacce rilevanti, delegando alla class effettiva e aggiungendo funzionalità, come ad esempio il tuo AOP.

Nel tuo esempio precedente stai chiamando direttamente sulla class, mentre se quell’istanza di class viene iniettata in un altro come bean Spring, viene iniettata come proxy, e quindi le chiamate al metodo saranno invocate sul proxy (e gli aspetti verranno triggersti )

Se si desidera ottenere quanto sopra, è ansible suddividere method2 / method2 in bean separati oppure utilizzare un framework AOP non orientato alla molla.

Il documento Spring lo descrive dettagliatamente e un paio di soluzioni alternative (incluso il mio primo suggerimento sopra)

Può essere fatto con l’auto iniezione. Puoi chiamare il metodo interno attraverso l’istanza iniettata:

 @Component public class Foo { @Resource private Foo foo; public void method1(){ .. foo.method2(); .. } public void method2(){ .. } } 

Dalla spring 4.3 puoi farlo anche usando @Autowired.

A partire da 4.3, @Autowired considera anche i riferimenti self per l’iniezione, ovvero i riferimenti al bean attualmente iniettato.

Ho avuto lo stesso tipo di problema e ho superato applicando Spring ApplicationContextAware , BeanNameAware e implementando i metodi corrispondenti come di seguito.

 class ABC implements ApplicationContextAware,BeanNameAware{ @Override public void setApplicationContext(ApplicationContext ac) throws BeansException { applicationContext=ac; } @Override public void setBeanName(String beanName) { this.beanName=beanName; } private ApplicationContext applicationContext; private String beanName; } 

poi ho sostituito this. con ((ABC) applicationContext.getBean(beanName)). mentre chiama i metodi della stessa class. Ciò garantisce che le chiamate ai metodi della stessa class avvengano solo attraverso il proxy.

Quindi, method1()

  public void method1(){ ......... ((ABC) applicationContext.getBean(beanName)).method2(); ........... } 

Spero che questo ti aiuti.

Il framework Spring AOP è basato su “proxy” ed è spiegato molto bene qui: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-understanding- AOP-proxy

Quando Spring costruisce un bean configurato con un aspetto (come “ABC” nell’esempio), crea effettivamente un object “proxy” che si comporta come il bean reale. Il proxy semplicemente delega le chiamate all’object “reale” ma creando questo indiretto, il proxy ha la possibilità di implementare il “consiglio”. Ad esempio, il tuo consiglio può registrare un messaggio per ogni chiamata di metodo. In questo schema, se il metodo nell’object reale (“metodo1”) chiama altri metodi nello stesso object (ad esempio, metodo2), tali chiamate avvengono senza proxy nell’immagine, quindi non vi è alcuna possibilità di implementare alcun consiglio.

Nel tuo esempio, quando viene chiamato method1 (), il proxy avrà la possibilità di fare qualsiasi cosa debba fare, ma se method1 () chiama method2 (), non c’è alcun aspetto nell’immagine. Tuttavia, se method2 viene chiamato da un altro bean, il proxy sarà in grado di eseguire il consiglio.

Spero che questo ti aiuti.

Grazie, Raghu

Usando @Autowired funziona. Invece di chiamare il metodo interno come this.method() , puoi fare:

 @Autowired Foo foo; 

e poi chiamando:

 foo.method2(); 

Non è ansible ciò che vuoi ottenere. Una spiegazione è nella documentazione di riferimento di spring .