Mybatis源码分析第三节课

一. Mybatis的核心对象 如何与SqlSession建立的联系?

        我们现在使用Mybtais都是使用SqlSession.getMapper(xx)的形式,但是在之前Mybatis是由SqlSession.方法(namespace.id)的形式进行使用的,例如

SqlSession.insert()

SqlSession.update()

SqlSession.delete()等等

具体如下图所示,其中两个语法查询的结果都是一样的。

首先先给出一个结论,其实我们目前常用的形式,是Mybatis在之后更新的结果,但是在底层其实也是调用了SqlSession.方法(namespaec.id)[第二种格式]。

         EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);

当我们使用这行代码的时候,我们有没有想过这样的问题??

EmpMapper是接口类型,这条语句肯定是将EmpMapper的实现类赋值给了empMapper,使用了java的多态形式。

那我们有没有想过:

1.EmpMapper的实现类在那里?

这个问题,我们直接给出答案,其实是使用了动态字节码技术,在JVM 运行时创建,在JVM运行结束后,消失啦。

2.如何创建EmpMapper的实现类呢?

  使用了代理 (动态代理)的方法

补充:使用代理的几种情况

            a. 为原始对象(目标)增加【额外功能】 
             b. 远程代理 1.网络通信 2.输出传输 (RPC)Dubbo 
             c. 接口实现类,我们看不见实实在在的类文件,但是运行时却能体现出来。
                无中生有

其实是使用JDK的动态代理(基于接口的形式),目前先大概了解,在后面我们将自己实现一下动态代理,将第二种形式和第一种形式联系起来。

3.实现类如何进行实现的

对于这个,我们可以结合前面,可以得到这样的理解

interface EmpMapper {

    List<Emp>  getAllEmp();

    int  save(Emp emp);

}

通过动态代理 我们得到的实现类应该是这个样子

EmpMapperImpl implements EmpMapper {

    List<Emp> getAllEmp(){

         sqlSession.selectlist(namespace.id)

          接下来就是在更底层调用我们上2节课的知识

                         ---  Executor

                                -- statementHandler

                                    --ParameterHandler   ResultSetHandler 

                                        --  TypeHandler

}

    int save(){

         SqlSession.insert(namespace.id,参数)

   }

}

二.自己大概实现一下动态代理

书写EmpMapper接口

进行测试

  @Test
    public void textAop() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSession sqlSession = sqlSessionFactoryBuilder.build(is).openSession();

        MyMapperProxy  myMapperProxy = new MyMapperProxy(sqlSession,EmpMapper.class);

        //获得sqlSession啦  自己使用一些动态代理
        /*
        第一个参数:类加载器
        第二个参数:原始类的接口
        第三个参数:InvocationHandler的实现类
         */
        EmpMapper empMapper =(EmpMapper) Proxy.newProxyInstance(Text.class.getClassLoader(),
                new Class[]{EmpMapper.class},
                myMapperProxy

        );

        List<Employee> list = empMapper.getAllEmployee();

        System.out.println(list);
    }

实现类如下


public class MyMapperProxy implements InvocationHandler {

    private SqlSession sqlSession;  //我们需要调用SqlSession.方法() 所以需要SqlSession的对象
    private Class nameClass;   // 用来获得namespace的

    public MyMapperProxy(SqlSession sqlSession, Class nameClass) {
        this.sqlSession = sqlSession;
        this.nameClass = nameClass;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //因为我们只有一个查询方法方法,所以就是调用selectList
        return  sqlSession.selectList(nameClass.getName() + "." + method.getName());
    }
}

进行测试,测试结果如下:

所以可以得知我们的分析是没有问题的。

三.简单通过源码去了解动态代理的实现

对于这个,我们根据我们上面的分析,mapperProxy 应该实现了InvocationHandler的接口

观察其invoke方法

观察execute方法

所以,我们通过这就明白了Mybatis的第一种形式与第二种形式的联系啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值