显然,Mybatis的插件机制是非常重要的一环,如果不会这个,估计都不好意思跟别人说自己会Mybatis.
首先,写了1个自定义的MyPlugin
package plugin;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
public class MyPlugin implements Interceptor {
private String prop1;
private String prop2;
@Override
public Object intercept(Invocation invocation) throws Throwable {
new Exception().printStackTrace();
return invocation;
}
@Override
public Object plugin(Object target) {
new Exception().printStackTrace();
// if(target instanceof StatementHandler){
// StatementHandler handler=(StatementHandler)target;
// System.out.println("----------------"+handler.getBoundSql().getSql());
// }
return target;
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
}
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
执行一个范例,打印内容如下:
java.lang.Exception
at plugin.MyPlugin.plugin(MyPlugin.java:21)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:33)
at org.apache.ibatis.session.Configuration.newExecutor(Configuration.java:605)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:110)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:50)
at test.Test.business(Test.java:35)
at test.Test.main(Test.java:27)
java.lang.Exception
at plugin.MyPlugin.plugin(MyPlugin.java:21)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:33)
at org.apache.ibatis.session.Configuration.newParameterHandler(Configuration.java:556)
at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:72)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:42)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:48)
at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:572)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:123)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:212)
at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:227)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:72)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:66)
at com.sun.proxy.$Proxy5.deleteRole(Unknown Source)
at test.Test.business(Test.java:57)
at test.Test.main(Test.java:27)
java.lang.Exception
at plugin.MyPlugin.plugin(MyPlugin.java:21)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:33)
at org.apache.ibatis.session.Configuration.newResultSetHandler(Configuration.java:564)
at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:73)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:42)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:48)
at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:572)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:123)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:212)
at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:227)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:72)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:66)
at com.sun.proxy.$Proxy5.deleteRole(Unknown Source)
at test.Test.business(Test.java:57)
at test.Test.main(Test.java:27)
java.lang.Exception
at plugin.MyPlugin.plugin(MyPlugin.java:21)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:33)
at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:575)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:123)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:212)
at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:227)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:72)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:66)
at com.sun.proxy.$Proxy5.deleteRole(Unknown Source)
at test.Test.business(Test.java:57)
at test.Test.main(Test.java:27)
总结就是:
Executor
ParameterHandler
ResultSetHandler
StatementHandler
好,我们先研究插件的接口类
/**
* 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 {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
---下面是关于插件的初始化
at plugin.MyPlugin.<init>(MyPlugin.java:13)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.pluginElement(XMLConfigBuilder.java:248)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:134)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:111)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:82)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:65)
at test.Test.main(Test.java:23)
定位到代码如下:
private void pluginElement(XNode parent) throws Exception {
// 如果定义了plugin节点
if (parent != null) {
// 遍历每1个子节点
for (XNode child : parent.getChildren()) {
// 获取interceptor的值
String interceptor = child.getStringAttribute("interceptor");
// 其它子节点作为属性存在
Properties properties = child.getChildrenAsProperties();
// 指定的interceptor实例化,所以传递的这个类必须实现Interceptor接口
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
// 属性设置,自己实现
interceptorInstance.setProperties(properties);
// 非常重要
configuration.addInterceptor(interceptorInstance);
// 看到这里了
}
}
}