# mybatis插件


<!--more-->

## 1.插件介绍
Mybati s作为一个应用广泛的优秀的ORM开源框架，这个框架具有强大的灵活性，在四大组件
(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插 件扩
展机制。Mybatis对持久层的操作就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进 行
拦截，对mybatis来说插件就是拦截器，用来增强核心对象的功能，增强功能本质上是借助于底层的 动
态代理实现的，换句话说，MyBatis中的四大对象都是代理对象  
MyBatis所允许拦截的方法如下：
- 执行器Executor (update、query、commit、rollback等方法)；
- SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方法)；
- 参数处理器ParameterHandler (getParameterObject、setParameters方法)；
- 结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法)；

## 2.插件原理
插件具体是如何拦截并附加额外的功能的呢？以ParameterHandler来说
```java
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,Object object, BoundSql sql, InterceptorChain interceptorChain){
        ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
        parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
        return parameterHandler;
}

public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
        target = interceptor.plugin(target);
    }
    return target;
}
```
interceptorChain保存了所有的拦截器(interceptors)，是mybatis初始化的时候创建的。调用拦截器链
中的拦截器依次的对目标进行拦截或增强。interceptor.plugin(target)中的target就可以理解为mybatis
中的四大对象。返回的target是被重重代理后的对象

## 3.使用示例
如果我们想要拦截Executor的query方法，那么可以这样定义插件：
```java
@Intercepts({
    @Signature(
        type = Executor.class,
        method = "query",
        args= {MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
    )
})
public class ExeunplePlugin implements Interceptor {
//省略逻辑
}
```
除此之外，我们还需将插件配置到sqlMapConfig.xm l中
```xml
<plugins>
    <plugin interceptor="com.example.demo.plugin.ExamplePlugin"></plugin>
</plugins>
```
Mybatis 插件接口-Interceptor
- Intercept方法，插件的核心方法
- plugin方法，生成target的代理对象
- setProperties方法，传递插件所需参数

## 4.分页插件
- maven依赖
```xml
    <!-- 分页助手 -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.7.5</version>
    </dependency>
    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>
```
- sqlMapConfig.xml配置
```xml
<!--注意：分页助手的插件 配置在通用馆mapper之前-->
<plugin interceptor="com.github.pagehelper.PageHelper">
    <!-- 指定方言 -->
    <property name="dialect" value="mysql"/>
</plugin>
```
- 代码示例
```java
/**
 * 测试分页
 */
@Test
public void test2() {
    UserMapper mapper = session.getMapper(UserMapper.class);
    PageHelper.startPage(1, 2);
    List<User> users = mapper.findAll();
    for (User user : users) {
    System.out.println(user);
    }

    PageInfo<User> pageInfo = new PageInfo<>(users);
    System.out.println("总条数：" + pageInfo.getTotal());
    System.out.println("总页数：" + pageInfo.getPages());
    System.out.println("当前页：" + pageInfo.getPageNum());
    System.out.println("每页显示的条数：" + pageInfo.getPageSize());
}
```

## 5.通用Mapper
- 引入依赖
```xml
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>3.1.2</version>
</dependency>
```
- sqlMapConfig.xml配置
```xml
<plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor">
    <!--指定当前通用mapper接口使用的是哪一个-->
    <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
</plugin>
```
- 代码示例
由于extends Mapper<T>，有很多通用方法可直接调用，但一般我们现在不用这，mybatis-plus会更好用些
```java
/**
 * 测试通用mapper
 * extends Mapper<T>
 */
@Test
public void test3() {
    UserMapperPluginMapper mapper = session.getMapper(UserMapperPluginMapper.class);
    User user = new User();
    user.setId(8);
    User user1 = mapper.selectOne(user);
    System.out.println(user1);
}
```



  


















