L'une des fonctions des intercepteurs est que nous pouvons intercepter les appels de certaines méthodes. Nous pouvons choisir d'ajouter de la logique avant et après l'exécution de ces méthodes interceptées, ou de supprimer ces méthodes interceptées et d'exécuter notre propre logique. .
Par exemple, pour l'Executor de mybatis, il existe plusieurs implémentations : BatchExecutor, ReuseExecutor, SimpleExecutor et CachingExecutor lorsque les méthodes de requête de ces Executor. les interfaces ne le peuvent pas. Lorsque nos exigences sont satisfaites, nous pouvons construire un intercepteur pour implémenter notre propre méthode de requête ; les intercepteurs sont généralement implémentés dynamiquement à l'aide d'aop.
Principe de l'intercepteur
Pour mybatis, nous pouvons définir notre propre intercepteur via l'interface de l'intercepteur. Définition de l'interface de l'intercepteur : La méthode du plugin
package org.apache.ibatis.plugin; import java.util.Properties; public interface Interceptor { Object intercept(Invocation invocation) throws Throwable; Object plugin(Object target); void setProperties(Properties properties); }
est principalement utilisée pour encapsuler l'objet cible. Grâce à cette méthode, nous pouvons décider d'intercepter puis décider quel type d'objet cible renvoyer.
La méthode d'interception est la méthode qui est exécutée lors de l'interception. setProperties est principalement utilisé pour spécifier les propriétés dans le fichier de configuration. Cette méthode sera exécutée lorsque la configuration initialisera l'intercepteur actuel. Il existe une classe de plugin dans mybatis, qui inclut la méthode statique wrap, il peut être déterminé si l'objet. à renvoyer est la cible des objets ou des agents.
package org.apache.ibatis.plugin; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.ibatis.reflection.ExceptionUtil; public class Plugin implements InvocationHandler { private Object target; private Interceptor interceptor; private Map<Class<?>, Set<Method>> signatureMap; private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) { this.target = target; this.interceptor = interceptor; this.signatureMap = signatureMap; } public static Object wrap(Object target, Interceptor interceptor) { //解析获取需要拦截的类以及方法{*} Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor); Class<?> type = target.getClass(); //解析type是否存在需要拦截的接口{*} Class<?>[] interfaces = getAllInterfaces(type, signatureMap); //决定返回的对象是否为代理{*} if (interfaces.length > 0) { return Proxy.newProxyInstance( type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)); } //返回原目标对象 return target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Set<Method> methods = signatureMap.get(method.getDeclaringClass()); //如果当前执行的方法是定义的需要拦截的方法,则把目标对象,要拦截的方法以及参数封装为一个Invocation对象传递给拦截器方法intercept; //Invocation中定义了定义了一个proceed方法,其逻辑就是调用当前方法,所以如果在intercept中需要继续调用当前方法的话可以调用invocation的procced方法; if (methods != null && methods.contains(method)) { return interceptor.intercept(new Invocation(target, method, args)); } return method.invoke(target, args); } catch (Exception e) { throw ExceptionUtil.unwrapThrowable(e); } } //根据注解解析需要拦截的方法 //两个重要的注解:@Intercepts以及其值其值@Signature(一个数组) //@Intercepts用于表明当前的对象是一个Interceptor //@Signature则表明要拦截的接口、方法以及对应的参数类型。 private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) { Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class); if (interceptsAnnotation == null) { // issue #251 throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName()); } Signature[] sigs = interceptsAnnotation.value(); Map<Class<?>, Set<Method>> signatureMap = new HashMap<Class<?>, Set<Method>>(); for (Signature sig : sigs) { Set<Method> methods = signatureMap.get(sig.type()); if (methods == null) { methods = new HashSet<Method>(); signatureMap.put(sig.type(), methods); } try { Method method = sig.type().getMethod(sig.method(), sig.args()); methods.add(method); } catch (NoSuchMethodException e) { throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e); } } return signatureMap; } private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) { Set<Class<?>> interfaces = new HashSet<Class<?>>(); while (type != null) { for (Class<?> c : type.getInterfaces()) { if (signatureMap.containsKey(c)) { interfaces.add(c); } } type = type.getSuperclass(); } return interfaces.toArray(new Class<?>[interfaces.size()]); } }
Instance d'intercepteur
package com.mybatis.interceptor; import java.sql.Connection; import java.util.Properties; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; @Intercepts( { @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })}) public class TestInterceptor implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { Object result = invocation.proceed(); return result; } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { String p = properties.getProperty("property"); } }
Marqué d'abord comme un intercepteur avec @Intercepts et conçu le point d'interception via @Signatrue : le type de paramètre dans l'interface de l'intercepteur Executor est MappedStatement, la méthode de requête d'Object, RowBounds et ResultHandler ; la méthode d'interception appelle la méthode d'invocation continue pour effectuer l'appel de méthode actuel normalement.
Enregistrement des intercepteurs
L'enregistrement des intercepteurs se fait via l'élément plugin sous l'élément plugins dans le fichier de configuration Mybatis est défini dans l'enregistrement Quand. en utilisant un intercepteur, toutes les propriétés sous l'intercepteur correspondant seront d'abord injectées via la méthode setProperties de l'intercepteur. Tel que :
<plugins> <plugin interceptor="com.mybatis.interceptor.TestInterceptor"> <property name="property" value="拦截器配置"/> </plugin> </plugins>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!