In Spring Boot AOP, come ottenere l'annotazione di classe quando nel periodo "Around" del metodo?
Grazie per tutti gli amici qui. So come ottenere il parametro di annotazione per l'annotazione impostata su method
.
Mentre vorrei aggiungere l'annotazione nel Class
livello. Come recuperare l'attributo Class
nel metodo AOP Around?
A proposito, ho un'altra domanda, perché devo cambiare il valore della risposta da void
a Object
e ritorno pjp.proceed()
. Se il metodo non ha risposta, la richiesta si bloccherà.
Per il metodo che ha l'annotazione HasRole
@Around("@annotation(com.example.demo.aspect.annotation.HasRole) && @annotation(annotation)")
public void aroundHasRole(ProceedingJoinPoint pjp, HasRole annotation) throws Throwable {
log.info("value->>{}", annotation.value());
pjp.proceed();
}
Per la classe o il metodo che ha l'annotazione HasRole
@Around("(@within(com.example.demo.aspect.annotation.IsAdmin)"
+ "|| @annotation(com.example.demo.aspect.annotation.IsAdmin))")
public Object aroundHasRole(ProceedingJoinPoint pjp) throws Throwable {
<<How to get annotation information here?>>
return pjp.proceed();
}
Risposte
Come probabilmente avrai notato, non puoi associare informazioni da ||
rami diversi a un parametro del metodo di consulenza perché sarebbe ambiguo, vedi anche le mie risposte qui e qui . Quindi, se vuoi evitare brutte (e lente) riflessioni, fai ciò che ho raccomandato nelle altre risposte e scrivi due consigli distinti, scomponendo il codice comune in un metodo di supporto se evitare la duplicazione del codice è la tua preoccupazione qui. Qualcosa di simile (non testato, solo per darti un'idea della struttura del codice):
@Around("@within(annotation)")
public Object classIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
return commonIsAdmin(pjp, annotation);
}
@Around("@annotation(annotation)")
public Object methodIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
return commonIsAdmin(pjp, annotation);
}
public Object commonIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
// Here you would place all common advice code.
// Non-common code could remain in the original advice methods.
log.info("value->>{}", annotation.value());
return pjp.proceed();
}
perché devo modificare il valore della risposta da
void
aObject
e restituirepjp.proceed()
. Se il metodo non ha risposta, la richiesta si bloccherà.
A differenza di un consiglio @Before
o @After
, in un @Around
consiglio è possibile modificare il valore restituito saltando completamente l'esecuzione del metodo di destinazione non chiamando proceed()
o scartando o modificando il risultato di proceed()
. Sei completamente libero in ciò che vuoi restituire, deve solo corrispondere al tipo di ritorno del metodo di destinazione.
Detto questo, dovrebbe diventare chiaro che anche un metodo around Advice deve avere un tipo di ritorno corrispondente a quello del metodo o dei metodi di destinazione che intercetta. Può essere un tipo esatto come MyType
, un super tipo o semplicemente Object
(super tipo per tutti i tipi) se il tuo consiglio si rivolge a una moltitudine di tipi senza un super tipo comune. Il consiglio può anche avere un tipo di ritorno void
se (e solo se) restituiscono anche tutti i metodi di destinazione void
(altrimenti il consiglio semplicemente non corrisponderebbe a quei metodi, anche se il taglio a punti in quanto tale corrisponderebbe).
Quindi, se un consiglio intorno corrisponde è determinato da una combinazione del pointcut stesso e del tipo restituito. Puoi usarlo come uno strumento per limitare la corrispondenza del taglio di punti definendo un tipo di ritorno specifico (al quale dovresti quindi eseguire il cast del valore di ritorno di proceed()
perché proceed()
restituisce sempre un Object
).
A proposito, se il metodo target restituisce un tipo primitivo come int
, boolean
ecc., Il consiglio avvolge automaticamente il risultato in un Integer
o Boolean
.
Dovresti davvero leggere i manuali oi tutorial Spring AOP e AspectJ perché qui sto spiegando cose che possono essere trovate lì.
Aggiornamento: l'OP ha richiesto la documentazione relativa al binding dei parametri e una descrizione di come vengono determinati i nomi:
- È possibile specificare un
argNames
parametro per tutti i tipi di consulenza, ad esempio@Before
,@After
,@Around
. - Se quel parametro di annotazione è assente, Spring AOP cercherà di abbinare i nomi dei parametri del metodo di consulenza tramite le informazioni di debug del file di classe, se compilato. In caso contrario, in questo caso la corrispondenza fallirebbe.
- Quando si utilizza AspectJ completo con la tessitura in fase di compilazione invece di Spring AOP, la determinazione dei nomi funziona anche senza informazioni di debug perché il compilatore AspectJ può determinare le informazioni necessarie durante la compilazione.
Tutto questo è descritto nel manuale Spring AOP .
Ottieni la classe tramite la riflessione, ottieni le informazioni sul metodo fisso tramite la classe e ottieni l'annotazione sul metodo. In questo modo dovresti essere in grado di riflettere