【MyBatis框架】动态代理-MyBatis框架的代理模式

本文详细介绍了MyBatis框架中的动态代理机制,包括原生方法调用方式、JDK动态代理和CGLib动态代理的原理及实现。重点讨论了MyBatis如何使用JDK动态代理创建Mapper接口的代理对象,以及Mapper接口的注册和代理对象的获取过程。
摘要由CSDN通过智能技术生成

MyBatis框架的代理模式

通过前面的了解,我们大致知道了MyBatis框架的基本使用方式。但是,我们可能会有一个疑问,为什么Mapper接口没有实现类却能被正常调用呢?其实这是因为MyBatis在Mapper接口上使用了动态代理的一种非常规的用法。在了解这种用法之前,我们先来看看原生方法的使用。

原生方法的调用方式
  • 以查询操作为例,原生方法的调用会直接通过sqlSession会话调用相应的方法来达到查询的目的。代码如下:

  • 接口文件:

public interface StudentMapper {
   
    /**
     * 模糊查询
     */
    public List<Student> getStudentByName(String str);
}
  • XML文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tulun.dao.StudentMapper">
    <!--直接在参数上拼接通配符,进行模糊查询-->
    <select id="getStudentByName" resultType="com.tulun.pojo.Student">
        select * from Student where SName like #{
   SName}
    </select>
mapper>
  • 测试文件:
public class StudentMapper3Test {
   
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() {
   
        //mybatis配置文件
        String resource = "mybatis-config.xml";
        //通过mybatis提供的Resources类来得到配置文件流
        InputStream inputStream = null;
        try {
   
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
   
            e.printStackTrace();
        }

        //创建会话工厂,传输mybatis配置文件信息
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void getStudentByName(){
   
        //通过工厂得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //原生方法调用形式
        //通过方法接口进行调用
        List<Object> objects = sqlSession.selectList("com.tulun.dao.StudentMapper3.getStudentByName", "%L%");
        System.out.println(objects);
    }
}
  • 注意测试方式的不同:

    • 返回多个结果时,使用selectList方法。
    • 返回的结果不管是单个还是多个在resultType属性都是返回的Java对象全路径。
    • 返回单个结果对象使用selectOne
    • 对于增删改操作,同样可以使用此操作,其sqlSession对象也同样提供了其对应的方法。
  • 执行结果:

在这里插入图片描述

而在MyBatis的使用过程中,我们经常使用的是通过getMapper方法获取代理对象,形如:StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);方式,从而进行对接口的动态代理,接下来,我们看看什么是动态代理。

动态代理

动态代理其实是代理模式的一种,而代理模式其实是Java当中的一种设计模式。其结构如图所示:

在这里插入图片描述

这种模式就相当于一个公司生产了一个产品,但并不是由其开发人员去销售,而是由销售人员去销售。

代理模式的特点:

  • 代理模式中代理类和委托类是具有相同的接口。
  • 代理类的主要职责就是为委托类预处理消息,过滤消息等功能的实现。
  • 代理类的对象本身并不是真正的实现服务,而是通过委托类的对象的相关方法,来提供特定的一些服务。
  • 代理类和委托类之间存在关联关系,一个代理类的对象和一个委托类的对象相关联。
  • 访问实际对象,是通过代理对象来访问的。

代理模式的分类: 静态代理和动态代理。

  • 静态代理是在程序编译阶段就确定了代理对象。
  • 而动态代理是在程序运行阶段才确定代理对象。
  • 而在这里,我们仅仅来分析一下动态代理:

其中动态代理是在运行时根据Java代码指示动态生成的,相比较静态代理,优势在于方便对代理类的函数进行统一的处理,而不用修改每个代理类的方法。

Java中提供的动态代理方式有两种:JDK自带的动态代理CGLib实现的代理。下面来看看这两种方式的区别。

JDK自带的动态代理

JDK自带的代理方式是需要实现invocationHandler接口,并且实现invoke的方法来进行的。下面我们来自己实现一下这种代理方式:

  • 先提供一个共有的接口和委托类的实现。
  • 接口文件:
/**
 * 接口类
 * 	定义委托类和代理类共工的方法
 */
public interface IUser {
   
    void talk();
}
  • 委托实现类:
/**
 * 委托类
 * 	实现了接口Iuser中的talk方法
 */
public class User implements IUser {
   
    @Override
    public void talk() {
   
        System.out.println("doing User.talk");
    }
}
  • 要实现动态代理,需要首先创建一个实现了InvocationHandler接口的辅助类。
/**
 * 代理的辅助类
 */
public class UserProxy implements InvocationHandler {
   
    private Object object;
    
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值