mybatis加載plugins
上一篇講解了mybatis加載typeAliases的過程,mybatis加載别名的方法有3種,根據優先級,最優先的是注解,然後才是配置檔案,整個過程簡單的說,就是讀取相關的bean,然後儲存在TYPE_ALIASES集合裡面,供後面的使用。它主要的作用就是為類寫别名,使得mybatis在使用類的時候,可以直接使用别名,而不需要使用類名。
加載完typeAliases之後,接着就是加載plugins,在mybatis,plugins是非常有用的,它可以定義攔截器,對執行的sql語句進行攔截,是對mybatis的增強。
MyBatis 允許使用插件來攔截的方法調用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
在mybatis裡使用插件是非常簡單的,隻需實作 Interceptor 接口,并指定了想要攔截的方法簽名即可,下面舉例講解一下plugins的使用過程。
- 定義類,實作mybatis的Interceptor接口
@Intercepts(value = {@Signature(type= Executor.class,method = "query",args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class})})
public class MyInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("----------- 執行開始。。。。。 ---------");
// 調用方法,實際上就是攔截的方法
Object result = invocation.proceed();
System.out.println("----------- 執行結束。。。。。 ---------");
return result;
}
public Object plugin(Object target) {
return Plugin.wrap(target,this);
}
public void setProperties(Properties properties) {
}
}
- 在核心配置檔案裡,加上plugins配置
<plugins>
<plugin interceptor="com.gzwx.plugins.interceptor.inceptor">
</plugin>
上面攔截的是Executor裡面的query方法,其他的包括update、flushStatements等都不會攔截。同樣的,攔截其他例如ParameterHandler 、ResultSetHandler等方法是同樣的配置,隻是在簽名那裡需要修改一下。
再看加載plugins的源碼,通過調用pluginElement方法加載plugins插件,傳入的是核心配置檔案裡面的plugins節點資訊
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
//周遊該節點,擷取interceptor節點屬性
String interceptor = child.getStringAttribute("interceptor");
//擷取節點下的其他屬性
Properties properties = child.getChildrenAsProperties();
//這裡是根據節點配置的類名去執行個體化類,在這裡面,首先會去找上一步加載的别名裡面的
//TYPE_ALIASES集合,因為有的配置直接配置别名,而不是配置完整類名,如果在集合裡面找到
//那麼直接傳回集合裡面的執行個體,否則,根據配置的類名去通過反射機制找到類,并執行個體化
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
interceptorInstance.setProperties(properties);
//把插件類添加進configuration裡面,實際上就是加入到interceptorChain這個變量裡面,
//interceptorChain變量的類型就是InterceptorChain,攔截器鍊,它裡面有一個list,這個方法就是把這個執行個體放到裡面的list裡
configuration.addInterceptor(interceptorInstance);
}
}
}
configuration的addInterceptor如下
public void addInterceptor(Interceptor interceptor) {
interceptorChain.addInterceptor(interceptor);
}
InterceptorChain代碼如下:
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
public List<Interceptor> getInterceptors() {
return Collections.unmodifiableList(interceptors);
}
}
到這裡,加載plugins就完成了,在這裡,僅僅是把插件執行個體化到configuration裡面。