第一章:插件原理
- Mybatis 在四大对象( Executor 、ParameterHandler 、ResultSetHandler 、StatementHandler )创建的过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,从而实现在目标对象执行目标方法之前进行拦截的效果。
- Mybatis 允许在已经映射语句指定过程中的某一点进行拦截调用。
第二章:插件开发步骤及应用示例
插件开发步骤:
- ① 编写
Interceptor的实现类。 - ② 使用
@Intercepts注解完成插件签名。 - ③ 在全局配置文件中注册插件。
- ① 编写
示例:
- sql 脚本:
DROP TABLE IF EXISTS `employee`;CREATE TABLE `employee` (`id` int(11) NOT NULL AUTO_INCREMENT,`last_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`gender` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
- 导入相关 jar 包的 Maven 坐标:
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency>
- log4j.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8" /><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /></layout></appender><logger name="java.sql"><level value="debug" /></logger><logger name="org.apache.ibatis"><level value="info" /></logger><root><level value="debug" /><appender-ref ref="STDOUT" /></root></log4j:configuration>
- Employee.java
package com.sunxiaping.domain;public class Employee {private Integer id;private String lastName;private String email;private String gender;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +'}';}}
- EmployeeMapper.java
package com.sunxiaping.mapper;import com.sunxiaping.domain.Employee;public interface EmployeeMapper {Employee findById(Integer id);}
- MyInterceptor.java
package com.sunxiaping.plugin;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.plugin.*;import java.sql.Statement;import java.util.Properties;//定义拦截那个对象的那个方法的那个参数@Intercepts({@Signature(type = StatementHandler.class, method = "parameterize", args = Statement.class)})public class MyInterceptor implements Interceptor {/*** 拦截目标对象的目标方法的执行** @param invocation* @return* @throws Throwable*/public Object intercept(Invocation invocation) throws Throwable {System.out.println("--------MyInterceptor.intercept------------"+invocation.getMethod());//执行目标方法Object proceed = invocation.proceed();return proceed;}/*** 包装目标对象:为目标对象创建一个代理对象** @param target* @return*/public Object plugin(Object target) {System.out.println("------MyInterceptor--plugin-------"+target);//借助Plugin的wrap使用当前的拦截器包装目标对象Object wrap = Plugin.wrap(target, this);//为当前target创建的动态代理return wrap;}/*** 将插件注册时的properties属性设置进来** @param properties*/public void setProperties(Properties properties) {System.out.println("插件配置的信息 = " + properties);}}
- mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 注册插件 --><plugins><plugin interceptor="com.sunxiaping.plugin.MyInterceptor"><property name="username" value="xuweiwei"/><property name="password" value="123456"/></plugin></plugins><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://192.168.64.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="com/sunxiaping/mapper/EmployeeMapper.xml"/></mappers></configuration>
- 测试:
package com.sunxiaping;import com.sunxiaping.domain.Employee;import com.sunxiaping.mapper.EmployeeMapper;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class EmployeeTest {public static void main(String[] args) throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);Employee employee = employeeMapper.findById(1);System.out.println("employee = " + employee);sqlSession.close();}}
