Mybatis 插件的运行原理

核心对象

MyBatis 插件的运行是基于 JDK 动态代理 + 拦截器链实现

  • Interceptor 是拦截器,可以拦截 Executor, StatementHandle, ResultSetHandler, ParameterHandler 四个接口

    实际就是利用 JDK动态代理,生成对应的代理类实例,通过 InvocationHandler#invoke 实现拦截逻辑

  • InterceptorChain 是拦截器链,对象定义在 Configuration 类中, 实际是一个 List集合,元素就是 Interceptor接口的实现类

  • Invocation 是对方法、方法参数、执行对象和方法的执行的封装,就是对 InvocationHandler#invoke方法参数的封装

加载解析拦截器

mybatis-config.xml

<configuration>
    <plugins>
        <plugin interceptor="io.github.tangmonkmeat.MyInterceptor1" />
        <plugin interceptor="io.github.tangmonkmeat.MyInterceptor2"/>
    plugins>
configuration>

拦截器的解析是在 XMLConfigBuilder 对象的 parseConfiguration 方法中,

如果是 Mybatis ,则从 SqlSessionFactoryBuilder#build方法开始

如果是 springboot-mybatis-starter,则从 SqlSessionFactoryBean#buildSqlSessionFactory 开始

private void parseConfiguration(XNode root) {
    try {
        // issue #117 read properties first
        propertiesElement(root.evalNode("properties"));
        Properties settings = settingsAsProperties(root.evalNode("settings"));
        loadCustomVfs(settings);
        loadCustomLogImpl(settings);
        typeAliasesElement(root.evalNode("typeAliases"));
        // 开始加载解析插件的标签,添加到 Configuration
        pluginElement(root.evalNode("plugins"));

        objectFactoryElement(root.evalNode("objectFactory"));
        objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
        reflectorFactoryElement(root.evalNode("reflectorFactory"));
        settingsElement(settings);
        // read it after objectFactory and objectWrapperFactory issue #631
        environmentsElement(root.evalNode("environments"));
        databaseIdProviderElement(root.evalNode("databaseIdProvider"));
        typeHandlerElement(root.evalNode("typeHandlers"));
        mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: "

你可能感兴趣的:(Mybatis)