一、攔截器加載配置
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
interceptorInstance.setProperties(properties);
configuration.addInterceptor(interceptorInstance);
}
}
}
二、哪些位置可以加攔截器
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
executor = (Executor) interceptorChain.pluginAll(executor);
三、攔截器可以做哪些事情
@Intercepts({ @Signature(type = ParameterHandler.class, method = "setParameters", args = { PreparedStatement.class }) })
public class ParameterInterceptor implements Interceptor{
private static final String tag = ParameterInterceptor.class.getName();
private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
@Override
public Object intercept(Invocation invocation) throws Throwable {
ParameterHandler parameterHandler = (ParameterHandler)invocation.getTarget();
MetaObject metaParameterHandler= MetaObject.forObject(
parameterHandler, DEFAULT_OBJECT_FACTORY,
DEFAULT_OBJECT_WRAPPER_FACTORY);
Object parameterObj =metaParameterHandler
.getValue("parameterObject");
BoundSql boundSql = (BoundSql) metaParameterHandler
.getValue("boundSql");
MappedStatement mappedStatement = (MappedStatement) metaParameterHandler
.getValue("mappedStatement");
String id = mappedStatement.getId();
String className = id.substring(0, id.lastIndexOf("."));
Class<?> classObj = Class.forName(className);
//根據配置加密
TableSeg tableSeg = classObj.getAnnotation(TableSeg.class);
if(tableSeg!=null){
String[] fields = tableSeg.encryptFields();
if(fields.length>0){
EncryptParameter as = new EncryptParameterImpl(mappedStatement, parameterObj, boundSql);
as.encryptParamter(fields);
}
}
//繼續執行
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
// 當目標類是ParameterHandler類型時,才包裝目標類,否者直接返回目標本身,減少目標被代理的
// 次數
if (target instanceof ParameterHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
}
}
四、攔截器原理
executor = (Executor) interceptorChain.pluginAll(executor);
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
可以看到返回的是插件包裝後的對象,所有的攔截都會包裝,而攔截器plugin由具體攔截器實現,攔截器都需要實現Interceptor接口:public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
plugin用於包裝,因爲所有的攔截器都會包裝下,所以這個方法裏面需要針對性的過濾下,什麼攔截器就包裝什麼,比如ExecutorInterceptor攔截器:@Override
public Object plugin(Object target) {
// 當目標類是Executor類型時,才包裝目標類,否者直接返回目標本身,減少目標被代理的
// 次數
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
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());
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);
}
}