Mybatis3.5.1源码分析
- Mybatis-SqlSessionFactoryBuilder,XMLConfigBuilder,XPathParser源码解析
- Mybatis-Configuration源码解析
- Mybatis-事务对象源码解析
- Mybatis-数据源源码解析
- Mybatis缓存策略源码解析
- Mybatis-DatabaseIdProvider源码解析
- Mybatis-TypeHandler源码解析
- Mybatis-Reflector源码解析
- Mybatis-ObjectFactory,ObjectWrapperFactory源码分析
- Mybatis-Mapper各类标签封装类源码解析
- Mybatis-XMLMapperBuilder,XMLStatmentBuilder源码分析
- Mybatis-MapperAnnotationBuilder源码分析
- [Mybatis-MetaObject,MetaClass源码解析]https://www.jianshu.com/p/f51fa552f30a)
- Mybatis-LanguageDriver源码解析
- Mybatis-SqlSource源码解析
- Mybatis-SqlNode源码解析
- Mybatis-KeyGenerator源码解析
- Mybatis-Executor源码解析
- Mybatis-ParameterHandler源码解析
- Mybatis-StatementHandler源码解析
- Mybatis-DefaultResultSetHandler(一)源码解析
- Mybatis-DefaultResultSetHandler(二)源码解析
- Mybatis-ResultHandler,Cursor,RowBounds 源码分析
- Mybatis-MapperProxy源码解析
- Mybatis-SqlSession源码解析
- Mybatis-Interceptor源码解析
InterceptorChain
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.plugin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 拦截器链
* @author Clinton Begin
*/
public class InterceptorChain {
/**
* 拦截器集合
*/
private final List interceptors = new ArrayList<>();
/**
* 通知所有拦截器,通知所有拦截器对 {@code target} 进行个性化包装
* @param target 目标对象
* @return 经过所有拦截器进行个性化包装后的对象
*/
public Object pluginAll(Object target) {
//遍历所有拦截器
for (Interceptor interceptor : interceptors) {
//不断对target用拦截器包装再包装
target = interceptor.plugin(target);
}
// 经过所有拦截器进行个性化包装后的对象
return target;
}
/**
* 添加拦截器
* @param interceptor 拦截器
*/
public void addInterceptor(Interceptor interceptor) {
//将interceptor添加拦截器集合
interceptors.add(interceptor);
}
/**
* 返回拦截器集合
* @return 不可修改的拦截器集合
*/
public List getInterceptors() {
//Collections.unmodifiableList返回的对象其实是interceptors,但是这个返回对象修改会抛出异常
return Collections.unmodifiableList(interceptors);
}
}
Interceptor
/**
* Copyright 2009-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.plugin;
import java.util.Properties;
/**
* 拦截器
*
* @author Clinton Begin
*/
public interface Interceptor {
/**
* intercept:拦截
* 拦截目标对象的目标方法的执行
*/
Object intercept(Invocation invocation) throws Throwable;
/**
* 包装目标对象的:包装:为目标对象创建一个代理对象
* @param target
* @return
*/
Object plugin(Object target);
/**
* setProperties:
* 将插件注册时 的property属性设置进来
*/
void setProperties(Properties properties);
}
拦截器的实现例子:
因为源码并没有比较好的示例,所以我上网找了一个
拦截器的实现例子
Plugin
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.plugin;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.ibatis.reflection.ExceptionUtil;
/**
* @author Clinton Begin
*/
public class Plugin implements InvocationHandler {
/**
* 目标对象
*/
private final Object target;
/**
* 拦截器对象
*/
private final Interceptor interceptor;
/**
* 目标类-方法集
*/
private final Map, Set> signatureMap;
/**
*
* @param target 目标对象
* @param interceptor 拦截器
* @param signatureMap 目标类-方法集
*/
private Plugin(Object target, Interceptor interceptor, Map, Set> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;
}
/**
* 根据将 {@code interceptor} 的配置Intercepts注解信息 ,实现 {@code target} 的代理对象
* 并返回出去,从而实现调用{@code interceptor}的intercept方法
* @param target 目标对象
* @param interceptor 拦截器
* @return {@code target} 的代理对象,代理对象会回调Plugin的invoke方法,然后回调{@code interceptor}的intercept方法
*/
public static Object wrap(Object target, Interceptor interceptor) {
//将 interceptor 的配置Intercepts注解信息封装成存储拦截目标对象类,
//以及拦截目标对象类的方法集映射关系的HashMap
Map, Set> signatureMap = getSignatureMap(interceptor);
//获取target的类型
Class> type = target.getClass();
//获取type 的在signatureMap有所包含的所有接口类
Class>[] interfaces = getAllInterfaces(type, signatureMap);
//如果interfaces不是空数组
if (interfaces.length > 0) {
//新建一个继承interfaces的代理对象
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
/**
* 代理方法
* @param proxy 目标对象
* @param method 方法对象
* @param args 参数对象数组
* @return 方法对象的返回对象
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//获取声明method的类的指定方法集
Set methods = signatureMap.get(method.getDeclaringClass());
//如果方法集不为null且方法集包含method
if (methods != null && methods.contains(method)) {
//执行拦截器的intercept方法
return interceptor.intercept(new Invocation(target, method, args));
}
//如果不是指定的方法,直接执行目标方法
return method.invoke(target, args);
} catch (Exception e) {
//当e属于InvocationTargetException 和UndeclaredThrowableException的类型时,
// 会从中 获取更加精确的异常抛出。
throw ExceptionUtil.unwrapThrowable(e);
}
}
/**
* 将 {@code interceptor} 的配置Intercepts注解信息封装成存储拦截目标对象类,
* 以及拦截目标对象类的方法集映射关系的HashMap
* @param interceptor 拦截器
* @return 一个存储拦截目标对象类,以及拦截目标对象类的方法集映射关系的HashMap
*/
private static Map, Set> getSignatureMap(Interceptor interceptor) {
//获取Intercepts注解
Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
// issue #251
//如果拦截器没有配置Intercepts注解
if (interceptsAnnotation == null) {
//抛出异常
throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
//获取Intercepts注解中的所有Signature注解
Signature[] sigs = interceptsAnnotation.value();
//新建一个HashMap,用于存储拦截目标对象类,以及拦截目标对象类的方法集
Map, Set> signatureMap = new HashMap<>();
//遍历Signature注解数组
for (Signature sig : sigs) {
//获取Signature注解中指定的拦截目标对象类对应的方法集
Set methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
try {
//获取拦截目标对象类中对应Signature注解配置方法和参数类型的方法对象
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;
}
/**
* 获取 {@code type} 的在 {@code signatureMap} 有所包含的所有接口类
* @param type 目标对象类
* @param signatureMap 存储拦截目标对象类,以及拦截目标对象类的方法集的HashMap
* @return {@code type} 的在 {@code signatureMap} 有所包含的接口类数组
*/
private static Class>[] getAllInterfaces(Class> type, Map, Set> signatureMap) {
//新建一个HashSet,用于保存type的在signatureMap包含的接口类
Set> interfaces = new HashSet<>();
//如果目标对象类不为null
while (type != null) {
//目标对象类的所有接口
for (Class> c : type.getInterfaces()) {
//如果signatureMap中包含这个接口类
if (signatureMap.containsKey(c)) {
//将接口类添加到interfaces
interfaces.add(c);
}
}
//取出type的父类重新赋值给type
type = type.getSuperclass();
}
//将interfaces集和转换成接口类数组
return interfaces.toArray(new Class>[interfaces.size()]);
}
}