Tout d'abord, le concept de base
section de ressort peut être appliquée à cinq types de notification:
Pré-notification (Avant): appel avis avant que la méthode cible est appelée
Après des conseils de retour (après): la notification d'appel après la méthode de cible d'achèvement (soit la sortie normale ou anormale)
notification de retour (après le retour): notification appel après l'exécution réussie de la méthode cible
notification d'exception (après lancement): notification d'appel lorsque la méthode cible génère une exception
Autour des conseils (autour): la mise en uvre de la coutume emballé après la méthode de notification à notifier, avant que la méthode est informé des appels et le comportement d'appel
L'ordre serait:
application de base ultérieure, volonté autour des conseils , avant de conseils , Après le retour des conseils , Retour à Nouvelles , anormale avis En vue d'atteindre, et démontre son ordre d'exécution.
En second lieu, l'application de base
revendications Indication
Vous pouvez copier le code ci-dessous, effectuer une vérification de la séquence ci-dessus.
@Aspect
Public class Test {
int statique privé étape = 0;
@Pointcut ( "@ annotation (com.chenyanwu.erp.erpframework.annotation.Log)") // l'expression pointcut
opération private void () {}
@Before (opération "()")
doBeforeTask () {publique vide
System.out.println (++ étape + "pré-notification");
}
@After (opération "()")
doAfterTask () {publique vide
System.out.println (++ + étape "notification arrière");
}
@AfterReturning (pointcut = "opération ()", retour = "retVal")
public void doAfterReturnningTask (Object retVal) {
System.out.println (++ + étape "notification de retour, la valeur de retour:" + retVal.toString ());
}
@AfterThrowing (pointcut = "opération ()", lancer = "ex")
doAfterThrowingTask public void (Exception ex) {
System.out.println (++ étape + "notification d'exception, les informations d'exception est:" + ex.getMessage ());
}
/ **
* Autour de types de conseils des paramètres nécessaires pour effectuer ProceedingJoinPoint
* Autour des conseils est similaire au processus de procurations dynamiques types ProceedingJoinPoint de paramètres peut décider si la méthode cible
* Et notification entourant doit revenir, à savoir la valeur de retour de la valeur de retour de la cible
* /
// @ Around ( "opération ()")
doAroundTask public Object (ProceedingJoinPoint PJP) {
Chaîne methodname = pjp.getSignature () getName () .;
Objet résultat = null;
try {
// Prénotification
System.out.println ( "méthode cible" + methodname + "paramètre start" + Arrays.asList (pjp.getArgs ()));
// exécuter la méthode cible
entraîner = pjp.proceed ();
// renvoie un avis
System.out.println ( "méthode objective" + methodname + "réussit, le retour" + résultat);
} Catch (e Throwable) {
// notification d'exception
System.out.println ( "méthode objective" + methodname + "renvoie une exception:" + e.getMessage ());
}
// après avis
System.out.println ( "méthode cible" + methodname + "End");
résultat retour;
}
}
Quel est le point d'entrée à noter: l'expression @Pointcut
Format:
exécution (modificateurs motif? ret de type-modèle de type déclarant motif? nom-motif (param-motif) jette motif?)
Chaque modèle entre parenthèses indiquent les éléments suivants:
- modificateur de match (modificateur de modèle?)
- match de valeur de retour (RET-type motif) * peut représenter une valeur de retour, et ainsi le chemin complet de la classe
- match Classpath (-modèle déclarant type?)
- Correspondant nom de la méthode (nom-motif) ou peut représenter tous les noms de méthode de tous les procédés représentatifs au début du jeu,
- paramètres assortis ((param-motif)) peut spécifier un type particulier de paramètres, parmi la pluralité de paramètres « » séparés, chaque paramètre peut être utilisé « » pour représenter - correspondre à tout type de paramètres, tels que (String) indique une correspondance le procédé paramètre de chaîne, (, String) représente le processus d'appariement a deux paramètres, le premier paramètre peut être tout type, et le second paramètre est le type de chaîne, peut être (...) représente zéro ou plusieurs paramètre arbitraire
- concordance des types d'exception (jette motif?)
- Qui a suivi derrière « ? » Est facultatif
exemple:
1) l'exécution (* (...))
// moyens correspondent à toutes les méthodes
2) exécution (public * com. Savage.service.UserService. (...))
// indique une com.savage.server.UserService match toutes les méthodes publiques
3) exécution (* com.savage.server .... (...))
// Toutes les méthodes représentées dans les sous-paquets et les paquets correspondants com.savage.server
En troisième lieu, le combat de gestion des logs
Avec la compréhension ci-dessus de l'application de base, maintenant nous collons directement le code:
1, paquet de pot dépendent
org.springframework.boot
printemps-boot-démarreur-aop
2, annotations personnalisées
@Target (ElementType.METHOD)
@Retention (RetentionPolicy.RUNTIME)
@interface publique Log {
Valeur de chaîne () par défaut « »;
}
3, mettre en uvre l'aspect
@Aspect
@Order (5)
@component
public class {LogAspect
enregistreur privé Logger = LoggerFactory.getLogger (LogAspect.class);
@Autowired
privé ErpLogService LogService;
@Autowired
ObjectMapper objectMapper;
privé ThreadLocal startTime = new ThreadLocal ();
@Pointcut ( "annotation @ (com.chenyanwu.erp.erpframework.annotation.Log)")
pointcut public void () {
}
/ **
* Pré-notification, à intercepter avant l'opération de couche contrôleur
*
* @Param point d'entrée JoinPoint
* /
@Before ( "pointcut ()")
doBefore public void (JoinPoint JoinPoint) {
// Obtenez le temps d'appel en cours
startTime.set (new Date ());
}
/ **
* Rendement normal
*
* @Param point d'entrée JoinPoint
* @param RVT résultats normaux
* /
@AfterReturning (pointcut = "pointcut ()", retour = "RVT")
doAfter public void (JoinPoint JoinPoint, objet RVT) throws Exception {
handleLog (Joinpoint, null, RVT);
}
/ **
* Interception des messages d'exception
*
* @Param JoinPoint
* @Param e
* /
@AfterThrowing (pointcut = "pointcut ()", lancer = "e")
doAfter public void (JoinPoint JoinPoint, Exception e) throws Exception {
handleLog (Joinpoint, e, null);
}
@Async
handleLog private void (finale JoinPoint JoinPoint, exception finale e, objet RVT) throws Exception {
// recueillir les commentaires
Procédé Method = getMethod (Joinpoint);
Connexion log = getAnnotationLog (méthode);
if (log == null) {
retour;
}
Date maintenant = new Date ();
// manipuler la table du journal de base de données
ErpLog erpLog = new ErpLog ();
erpLog.setErrorCode (0);
erpLog.setIsDeleted (0);
// information de demande
HttpServletRequest request = ToolUtil.getRequest ();
erpLog.setType (ToolUtil.isAjaxRequest (requête) "demande Ajax": "demande générale");
erpLog.setTitle (log.value ());
erpLog.setHost (request.getRemoteHost ());
erpLog.setUri (request.getRequestURI () toString ().);
// erpLog.setHeader (request.getHeader (HttpHeaders.USER_AGENT));
erpLog.setHttpMethod (request.getMethod ());
erpLog.setClassMethod (joinPoint.getSignature () getDeclaringTypeName () + + joinPoint.getSignature () getName (). "".);
Méthode de demande de valeur du paramètre
Objet args = joinPoint.getArgs ();
demande Méthodes Nom du paramètre
LocalVariableTableParameterNameDiscoverer u
= New LocalVariableTableParameterNameDiscoverer ();
Chaîne paramNames = u.getParameterNames (méthode);
if (args! = null && paramNames! = null) {
StringBuilder params = new StringBuilder ();
params = handleParams (params, args, Arrays.asList (paramNames));
erpLog.setParams (params.toString ());
}
Chaîne retString = JsonUtil.bean2Json (RVT);
erpLog.setResponseValue (? retString.length ()> 5000 JsonUtil.bean2Json ( "données de paramètres de demande ne montre pas trop"): retString);
if (e! = null) {
erpLog.setErrorCode (1);
erpLog.setErrorMessage (e.getMessage ());
}
Date stime = startTime.get ();
erpLog.setStartTime (stime);
erpLog.setEndTime (maintenant);
erpLog.setExecuteTime (now.getTime () - stime.getTime ());
erpLog.setUsername (MySysUser.loginName ());
HashMap browserMap = ToolUtil.getOsAndBrowserInfo (demande);
erpLog.setOperatingSystem (browserMap.get ( "os"));
erpLog.setBrower (browserMap.get ( "navigateur"));
erpLog.setId (IdUtil.simpleUUID ());
logService.insertSelective (erpLog);
}
/ **
* L'existence de notes, si vous obtenez
* /
Connexion privé getAnnotationLog (méthode Method) {
si (méthode! = null) {
retour method.getAnnotation (Log.class);
}
return null;
}
Méthode privée getMethod (JoinPoint JoinPoint) {
signature Signature = joinPoint.getSignature ();
MethodSignature signature methodSignature = (MethodSignature);
Procédé Method = methodSignature.getMethod ();
si (méthode! = null) {
Procédé de retour;
}
return null;
}
handleParams de StringBuilder privées (StringBuilder params, objet args, Liste paramNames) lancers francs JsonProcessingException {
pour (int i = 0; i