Il y a beaucoup de débutants Java qui ne savent pas grand-chose sur l'intercepteur d'intercepteur Mybatis. Ici, je vais organiser le prochain article pour expliquer l'intercepteur MyBatis Interceptor en Java.
Cet article analyse principalement le mécanisme du plug-in de MyBatis, qui est en fait la mise en œuvre du modèle de chaîne de responsabilité de Java Dynamic Proxy.
Selon la documentation officielle. MyBatis permet uniquement d'intercepter les méthodes suivantes, qui détermine les paramètres de signature de l'annotation intercepteur.
Le code est le suivant
Exécuteur (mise à jour, requête, flushstatements, engagement, rollback, getTransaction, close, isclose) ParameterHandler (getParameterObject, setParameters) ResultsEtHandler (HandlerResultSets, handleOutputParameters) instructionHandler (préparer, paramètre, lot, mise à jour, requête)
Le code source du traitement intercepteur est le suivant, où interceptorchain.pluginall (..) est un tissage d'intercepteur personnalisé:
Le code est le suivant
/ * Méthode dans org.apache.ibatis.Session.Configuration Classe * / public ParameterHandler NewParameterHandler (MaptedStatement MaptedStatement, Object ParameterObject, BOUNDSQL BOUNDSQL) {ParameterHandler ParameterHandler = MaptedStatement.getLang (). / * Intercept ParameterHandler * / ParameterHandler = (ParameterHandler) interceptorchain.pluginall (ParamètreHandler); Return ParameterHandler;} Résultats publicsHandler NewResultSethandler (exécuteur testamentaire, Maptedstatement Maptedstatement, Rowbounds Rowbounds, ParameterHandler ParameterHandler, Resulthandler Resulthandler, BoundsQL Boundsql) {ResultsEthandler ResultsEthandler = New DefaultreSultSetHandler, (exécutoror, MAPPEDSTATEM Resulthandler, BoundsQL, Rowbounds); / * Intercepter les résultats de l'InterceptorChain.Pluginall (ResultsEthandler); Renvoie RésultatsHandler;} public StatementHandler NewStatementHandler (exécuteur testamentaire, mappés de statement MaptedStatement, objet ParameterObject, Rowbounds Rowbounds, Resulthandler Resulthandler, BoundsQL BoundsQL) {StatutHandler Statementhandler = New RoutingStatumentHandler (Executeur, MappEdstatement, paramètre, paramètre, Rowbounds, Réponse, Mappedstamation boundsql); / * Intercept StatementHandler * / instructionHandler = (instructionHandler) interceptorchain.pluginall (instructionHandler); return instructionHandler;} public Executor NewExEcutor (transaction transaction, exécutorype exécutorType) {exécutorType = exécutorType == null? DefaultExECutOrType: exécutorType; exécutorType = exécutorType == null? EXECTIONTETTYPE.SIMPLE: EXECTINGETYPE; Exécuteur testamentaire; if (exécutorType.batch == exécutorType) {exécutor = new BatchExecutor (this, transaction); } else if (exécutorType.reuse == exécutorType) {exécutor = new ReuseExECUTOR (this, transaction); } else {exécutor = new SimpleExecutor (this, transaction); } if (cacheenabled) {exécutor = new CachingExecutor (exécuteur); } / * Intercept Executor * / exécutor = (exécuteur) interceptorchain.pluginall (exécuteur); return exécuteur exécuteur;} Pour implémenter un intercepteur personnalisé, il vous suffit d'implémenter l'interface intercepteur. Le code général est le suivant:
Le code est le suivant
/ * La méthode et les paramètres de l'annotation qui indiquent quelle interface pour intercepter * / @ intercepts ({@Signature (type = instructionHandler.class, method = "prépare", args = {connexion.class})}) public classe publique votre Interceptor implémente interceptor {public objet intercept (invocation invocation) lance lanceable {dosomething ();); / * Remarque: Ici, la méthode invocation.proceed () est réellement utilisée pour terminer l'appel de traversée de la chaîne interceptorchain (c'est-à-dire pour exécuter toutes les méthodes d'interception enregistrées de l'intercepteur), et à l'appel de méthode d'origine de l'objet proxy final * / return invocation.proceed (); } / * Générer un proxy vers la cible cible, et l'annotation de @Intercepts est utilisée dans plugin.wrap * / @Override Public Object Plugin (cible d'objet) {/ * Lorsque la classe cible est de type de relevé de déclaration, la classe cible est enveloppée et aucun proxy dénué de sens est utilisée * / return (cible instanceof statementHandler)? Plugin.wrap (cible, this): cible; } / * Utilisé pour définir les paramètres de configuration d'intercepteur personnalisés * / @Override public void SetProperties (Propriétés Propriétés) {}} Parmi eux, le code pour intercepter les appels se trouve dans plugin.wrap:
Le code est le suivant
/ * org.apache.ibatis.plugin.plugin Class * / public class Plugin implémente invocationhandler {/ * omettre le code ... * / public static wrap (cible d'objet, intercepteur intercepteur) {/ * voici pour obtenir la signature annotation = GeteignAmmap (interceptor); Classe <?> Type = cible.getClass (); / * Obtenez l'interface correspondant à la classe cible * / class <?> [] Interfaces = getAllInterfaces (type, signaturmap); if (interfaces.length> 0) {/ * Utilisez JDK Dynamic Proxy * / return proxy.newProxyInstance (type.getClassloader (), Interfaces, nouveau plugin (cible, intercepteur, signaturemap)); } return cible; } / * L'exécution de toutes les méthodes de la classe cible d'interception sera exécutée ici * / @Override Public Object Invoke (Proxy d'objet, méthode Method, objet [] args) lève Throwsable {try {set <méthode> Methods = SignAtMap.get (méthode.getDeclatingClass ()); if (Methods! = Null && méthodes.Contains (méthode)) {/ * Exécuter la méthode interceptor * / return interceptor.intercept (new invocation (cible, méthode, args)); } return method.invoke (cible, args); } catch (exception e) {lancer exceptionUtil.unwrapthrowable (e); }} / * Omettre le code ... * /}Vous pouvez voir que le code central de la conception d'intercepteur MyBatis est relativement simple, mais il est suffisamment flexible. Lorsque vous l'utilisez dans la pratique, veillez à ne pas être un proxy dénué de sens (plugin.wrap).