mybatis拦截器不能拦截哪个类_信号发生器的使用方法总结

mybatis拦截器不能拦截哪个类_信号发生器的使用方法总结文章目录1.基础介绍1.1.核心对象1.2.执行过程2.实现步骤2.1.添加注解2.1.1.type2.1.2.method2.1.3.args2.2.方法实现2.2.1.intercept2.2.2.plugin2.2.3.setProperties3.代码示例MyBatis拦截器可以做的工作:SQL修改,分页操作,数据过滤,SQL执行时间性能监控等。1.基础介绍1.1.核心对象从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个:Con

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺


MyBatis拦截器可以做的工作:SQL修改,分页操作,数据过滤,SQL执行时间性能监控等。

1. 基础介绍

1.1. 核心对象

MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个:

  • Configuration:初始化基础配置,比如MyBatis的别名等,一些重要的类型对象,如插件,映射器,ObjectFactorytypeHandler对象,MyBatis所有的配置信息都维持在Configuration对象之中。
  • SqlSessionFactorySqlSession工厂。
  • SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要的数据库增删改查功能。
  • ExecutorMyBatis的内部执行器,它负责调用StatementHandler操作数据库,并把结果集通过ResultSetHandler进行自动映射,另外,它还处理二级缓存的操作。
  • StatementHandlerMyBatis直接在数据库执行SQL脚本的对象。另外它也实现了MyBatis的一级缓存。
  • ParameterHandler:负责将用户传递的参数转换成JDBC Statement所需要的参数。是MyBatis实现SQL入参设置的对象。
  • ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合。是MyBatisResultSet集合映射成POJO的接口对象。
  • TypeHandler:负责Java数据类型和JDBC数据类型之间的映射和转换。
  • MappedStatementMappedStatement维护了一条<select|update|delete|insert>节点的封装。
  • SqlSource :负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回。
  • BoundSql:表示动态生成的SQL语句以及相应的参数信息。

1.2. 执行过程

mybatis拦截器不能拦截哪个类_信号发生器的使用方法总结

2. 实现步骤

  • 写一个实现org.apache.ibatis.plugin.Interceptor接口的拦截器类,并实现其中的方法。
  • 添加@Intercepts注解,写上需要拦截的对象和方法,以及方法参数。
  • Spring项目注意添加@Component注解即可,使其成为Spring管理的一个Bean

2.1. 添加注解

MyBatis拦截器默认可以拦截的类型只有四种,即四种接口类型ExecutorStatementHandlerParameterHandlerResultSetHandler。对于我们的自定义拦截器必须使用MyBatis提供的@Intercepts注解来指明我们要拦截的是四种类型中的哪一种接口。

注解 描述
@Intercepts 标志该类是一个拦截器
@Signature 指明该拦截器需要拦截哪一个接口的哪一个方法

@Signature注解的参数:

参数 描述
type 四种类型接口中的某一个接口,如Executor.class
method 对应接口中的某一个方法名,比如Executorquery方法。
args 对应接口中的某一个方法的参数,比如Executorquery方法因为重载原因,有多个,args就是指明参数类型,从而确定是具体哪一个方法。
@Intercepts({ 
   
    @Signature(type = Executor.class, method = "query", args = { 
   MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "prepare", args = { 
   Connection.class, Integer.class}),
    @Signature(type = ParameterHandler.class, method = "setParameters", args = { 
   PreparedStatement.class}),
    @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { 
   Statement.class})
})

2.1.1. type

MyBatis拦截器默认会按顺序拦截以下的四个接口中的所有方法:

org.apache.ibatis.executor.Executor  //拦截执行器方法
org.apache.ibatis.executor.statement.StatementHandler  //拦截SQL语法构建处理
org.apache.ibatis.executor.parameter.ParameterHandler  //拦截参数处理
org.apache.ibatis.executor.resultset.ResultSetHandler  //拦截结果集处理

具体是拦截这四个接口对应的实现类:

org.apache.ibatis.executor.CachingExecutor
org.apache.ibatis.executor.statement.RoutingStatementHandler
org.apache.ibatis.scripting.defaults.DefaultParameterHandler
org.apache.ibatis.executor.resultset.DefaultResultSetHandler

mybatis拦截器不能拦截哪个类_信号发生器的使用方法总结

2.1.2. method

这个可以根据MyBatis源码了解下。

2.1.3. args

根据参数类型区分重载的方法。

2.2. 方法实现

2.2.1. intercept

进行拦截的时候要执行的方法。该方法参数Invocation类中有三个字段:

  private final Object target;
  private final Method method;
  private final Object[] args;

可通过这三个字段分别获取下面的信息:

Object target = invocation.getTarget();//被代理对象
Method method = invocation.getMethod();//代理方法
Object[] args = invocation.getArgs();//方法参数
拦截接口 接口实现类
Executor CachingExecutor
StatementHandler RoutingStatementHandler
ParameterHandler DefaultParameterHandler
ResultSetHandler DefaultResultSetHandler

2.2.2. plugin

插件用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理,可以决定是否要进行拦截进而决定要返回一个什么样的目标对象,官方提供了示例:return Plugin.wrap(target, this);,可以在这个方法中提前进行拦截对象类型判断,提高性能:

    @Override
    public Object plugin(Object target) { 
   
        //只对要拦截的对象生成代理
        if(target instanceof StatementHandler){ 
   
            //调用插件
            return Plugin.wrap(target, this);
        }
        return target;
    }

MyBatis拦截器用到责任链模式+动态代理+反射机制;
所有可能被拦截的处理类都会生成一个代理类,如果有N个拦截器,就会有N个代理,层层生成动态代理是比较耗性能的。而且虽然能指定插件拦截的位置,但这个是在执行方法时利用反射动态判断的,初始化的时候就是简单的把拦截器插入到了所有可以拦截的地方。所以尽量不要编写不必要的拦截器。另外我们可以在调用插件的地方添加判断,只要是当前拦截器拦截的对象才进行调用,否则直接返回目标对象本身,这样可以减少反射判断的次数,提高性能。

2.2.3. setProperties

如果我们拦截器需要用到一些变量参数,而且这个参数是支持可配置的,类似Spring中的@Value("${}")application.properties文件获取自定义变量属性,这个时候我们就可以使用这个方法。

(1)在application.properties文件中添加配置:

mybatis.config-location=classpath:mybatis-config.xml

(2)在resources目录下添加mybatis-config.xml配置文件,并添加插件和属性配置。添加完需要注意去掉自定义MyBatis拦截器上的@Component注解,否则该拦截器相当于注册了两个,会执行两遍拦截方法。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <plugins>
        <plugin interceptor="com.example.demo.mapper.plugin.MyPlugin">
            <property name="key1" value="value1"/>
            <property name="key2" value="value2"/>
            <property name="key3" value="value3"/>
        </plugin>
    </plugins>
</configuration>

(3)在拦截器插件的setProperties方法中进行。这些自定义属性参数会在项目启动的时候被加载。

    @Override
    public void setProperties(Properties properties) { 
   
        System.out.println("key1=" + properties.getProperty("key1"));
        System.out.println("key2=" + properties.getProperty("key2"));
        System.out.println("key3=" + properties.getProperty("key3"));
    }

3. 代码示例

package com.example.demo.mapper.plugin;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Properties;

@Intercepts({ 
   
    @Signature(type = StatementHandler.class, method = "prepare", args = { 
   Connection.class, Integer.class})
})
public class MyPlugin implements Interceptor { 
   

    Properties properties = null;

    /** * 拦截方法逻辑 * 这里主要是通过反射去获取要执行的SQL相关信息,然后进行操作 */
    @Override
    public Object intercept(Invocation invocation) throws Throwable { 
   
        Object target = invocation.getTarget();//被代理对象
        Method method = invocation.getMethod();//代理方法
        Object[] args = invocation.getArgs();//方法参数
        // do something ...... 方法拦截前执行代码块
        Object result = invocation.proceed();
        // do something .......方法拦截后执行代码块
        return result;
    }

    /** * 生成MyBatis拦截器代理对象 */
    @Override
    public Object plugin(Object target) { 
   
        if(target instanceof StatementHandler){ 
   
            //调用插件
            return Plugin.wrap(target, this);
        }
        return target;
    }

    /** * 设置插件属性(直接通过Spring的方式获取属性,所以这个方法一般也用不到) * 项目启动的时候数据就会被加载 */
    @Override
    public void setProperties(Properties properties) { 
   
        //赋值成员变量,在其他方法使用。
        this.properties = properties;
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195539.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • GT911电容触摸屏使用[通俗易懂]

    GT911电容触摸屏使用[通俗易懂]一、介绍与硬件连接GT911、GT928、GT9147都属于GT9系列非单层多点触控芯片,他们支持的触控点数不同(GT928支持10个点、GT911支持5个点)、驱动和感应通道也可能不同。可是他们的寄存器和IIC通讯时序是相同的,也就是说驱动程序是兼容的。与主机的接口共有6PIN,分别为:VDD、GND、SCL、SDA、INT、RESET。INT、RESET不需要接上下拉电阻,可与主机直连。SCL、SDA需要接上拉电阻4.7K,毕竟400KHz的通信频率,没有上拉可能导致SCL、SDA边沿不够陡峭。R

  • IDEA插件-热部署:JRebel

    IDEA插件-热部署:JRebelspringboot项目开发过程中通常修改了某分部代码需要重启服务才能生效。通过JRebel插件可以实现热部署,避免了频繁重启服务。

  • 带通 带阻滤波器 幅频响应_二阶有源带通滤波器设计

    带通 带阻滤波器 幅频响应_二阶有源带通滤波器设计二阶有源带通滤波器设计1、背景对于微弱的信号的处理方式一般是:放大和滤波,这个过程中就涉及到放大电路的选取、滤波器的选择以及偏置电路的设计。本例以实例的方式讲解并附带参数计算、仿真、实物测试三个环节。 假设需要处理一个20mV的正弦信号,该信号的频率范围是15~35Hz,经过处理后幅值不超过3.3V,且需要经过带通滤波器滤除杂波。2、滤波器定义滤波电路又称为滤波器,是一种选频电路,能够使特定频率范…

  • mysql查看数据隔离级别_如何查看mysql数据库隔离级别

    mysql查看数据隔离级别_如何查看mysql数据库隔离级别CPUQuota=value该参数表示服务可以获取的最大CPU时间,value为百分数形式,高于100%表示可使用1核以上的CPU。与cgroupcpu控制器cpu.cfs_quota_us配置项对应。MemoryLimit=value该参数表示服务可以使用的最大内存量,value可以使用K,M,G,T等后缀表示值的大小。与cgroupmemory控制器…

  • Picasso闪退 Target must not be null error

    Picasso闪退 Target must not be null error

  • 取反是什么意思_1取反是多少

    取反是什么意思_1取反是多少很多编程语言使用~作为一元按位取反(NOT)操作符,Go重用^XOR操作符来按位取反://错误的取反操作funcmain(){fmt.Println(~2)//bitwisecomplementoperatoris^}//正确示例funcmain(){varduint8=2fmt.Printf(“%08b\n”,d)//00000010fmt.Printf(“%08b\n”

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号