这几天在学习mybatis的时候,在通过mapper映射来处理的时候,发现Mapper的接口竟然可以实例化,但是在我们学习java的时候曾经说过因为接口没有具体的方法实现,不能够被实例化,主要作用就是被类来多继承,但是我所看到的的确实是接口被实例化了,如下所示:
而这相比于其他的普通java测试里面来说,多了一个会话工厂,所以刚开始猜测可以是会话工厂的底层中有猫腻。
开始分析mybatis源码:
mybatis的部分Spring配置文件如下,跟踪其中id=”UserMapper”,考虑bean是如何创建的
通过这里我们看到了MapperFactoryBean类通过工厂来创建bean,然后在通过application.getBean("UserMapper")来获取id
,接着我们定位到org.mybatis.spring.mapper.MapperFactoryBean的源码中:
首先在这里我们得注意了,MapperFactoryBean.class它将类org.mybatis.spring.support.SqlSessionDaoSupport和接口org.springframework.beans.factory.FactoryBean给继承了,所以这就省去了我们自己手写工厂的过程了。
下面就是MapperFactoryBean.getObject()方法,获取初始化接口mapperInterface值
而里面的getSqlSession()方法就是其父类SqlSesionDaoSupport的,
而getSqlSession中的getMapper又是Session接口的
现在主要的是SqlSession是如何创建的,那我们又得找到SqlSessionDaoSupport类中寻找:
通过两个set大致就已经明白个所以然了。现在session的创建mapperInterface已经已经解决,现在分析bean的第二行
sqlSessionFactory是如何注入到MapperFactoryBean的,首先我们已经清楚了sqlSession的实现类是SqlSessionTemplate,然后我们找到它的getMapper()方法
又找到里面的getConfiguration()方法,可以看到,它首先调用了自身的getConfiguration()方法返回一个Configuration对象,然后再调用Configuration对象的getMapper方法
然后看getMapper()方法,查看geiConfiguration().getMapper(),
我们继续深入
现在基本上已经到了最低,已经可以看到
在这里,首先构造出一个MapperProxy对象,然后调用自身的newInstance(重载的另一个方法)方法。Bean最终在这里创建的。
第一次将一个问题找到底层,探寻它的根本才发现其实,查看源代码,发现它的工作原理其中并不难,只要你能够静下心来,慢慢发现,一定会有另外一番感悟。