一.概要
根据mybatis官方文档的介绍,插件的作用如下:
1.在源码中特定接口中的特定的前后接入自定义处理的逻辑;
可以接入的具体的接口以及方法如下如下:
//mybatis执行器;
1.Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
//mybatis查询参数处理类
2.ParameterHandler (getParameterObject, setParameters)
//mybatis查询结果集处理类
3.ResultSetHandler (handleResultSets, handleOutputParameters)
//mybatis参数处理(包括了前面的查询参数处理类,mybatis查询结果集处理类)
4.StatementHandler (prepare, parameterize, batch, update, query)
2.覆盖mybatis的运行环境;
二.使用
1.startDemo如下:
1.1自定义插件类实现Interceptor接口,重写 intercept方法;
1.2定义自定义注解
@Intercepts({
@Signature(type = Executor.class,
method = "query",
args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class }) })
注解说明:
type 表示,这个插件对那个接口的实现类起作用(只要概要中的4种);
method 表示,对实现类中那个接口起作用;
args = {MappedStatement.class,Object.class};
method 接口的参数列表对应的字节码对象;
1.3配置完成代码如下:
@Intercepts({
@Signature(type = Executor.class,
method = "query",
args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class }) })
public class ExamplePlugin implements Interceptor{
private static final Log log = LogFactory.getLog(ExamplePlugin.class);
public Properties properties = new Properties();
//对外提供获取Properties对象的方法;
public Properties getProperties() {
return properties;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
log.error("在具体方法之前执行");
Object returnObject = invocation.proceed();
log.error("在具体方法之后执行");
return returnObject;
}
public void setProperties(Properties properties) {
//
log.error("properties的数据是:"+properties.toString());
//mysql 的驱动的值就是从 配置文件中拿到;
//properties.setProperty("driver", //properties.getProperty("driver"));
//properties.setProperty("url", //"jdbc:mysql://cdb-ewlmquzk.bj.tencentcdb.com:10191/d//ata_shf");
//properties.setProperty("username", "root");
//properties.setProperty("password", "shenhufei_");
//log.error("properties中url是:"+properties.getProper//ty("url"));
//
this.properties = properties;
}
//插件的植入操作,就是插件该在哪个位置生效做的jdk代理
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
1.4在mybatis的核心配置文件中加上如下
<plugins>
<plugin interceptor="org.apache.ibatis.Amy.plugin.ConfigPlugin">
<!-- mybatis的自己的一些需要用的配置字段,相当于spring 的 @Value 注解 ,这些字段传入,后期可以去反向去修改mybatis的运行环境,eg:数据库配置,-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
</plugin>
</plugins>
1.4.1特殊说明
1.插件类上的注解 @Signature可以定义多个,表示这个方法将会在多个配置的位置都会生效;
2.当操作的是查询语句的时候,前后逻辑都会生效;当操作的是修改语句的时候,只有方法前的逻辑会有效;
3.setProperties
方法一般是不需要做任何处理,如果你想通过这个方式传递参数,是可以做的;
4.mybatis的核心配置文件中的标签的顺序必须是如下:<!-- 配置的标签的顺序必须是properties?,settings?,typeAliases?,
typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,
否则就会抛出异常
1.5测试类
public static void main(String[] args) throws IOException {
String resource = "org/apache/ibatis/Amy/mybatis-config.xml";//"mybatis-config.xml"
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
User user = session.selectOne("org.apache.ibatis.Amy.UserMapper.selectUser",1L);
}
测试打印的日志如下:
ERROR [main] - 在具体方法之前执行
ERROR [main] - BoundSql对象中的数据是:{"parameterMappings":[{"javaType":"java.lang.Long","mode":"IN","property":"id","typeHandler":{"rawType":"java.lang.Long"}}],"parameterObject":1,"sql":"select * from user where id = ?"}
ERROR [main] - 在具体方法之后执行
说明自定义插件的逻辑是生效了;
源码地址:有自己对myabtis全方位的注释说明和理解
https://github.com/shenhufei/mybatis_source_code_read.git