前言
经常看到一些项目模块中mapper没有实现类
而唯独使用了mapper.xml文件来执行
那这个接口文件是不是没有使用到或者是没有用
但是取消接口类好像又不大行
接口看似没用却用处很大
相信大家看到这篇文章都有差不多的疑问
1. 代码展示
通过代码辩证mapper可以不用实现类
mapper的接口类如下
public interface StudentDao {
List<Student> selectStudents();
}
具体xml的配置文件如下
<select id="selectStudents" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student order by id
</select>
写一个工具类主要用来实现sqlsession的对象获取
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
String config="mybatis.xml"; // 需要和你的项目中的文件名一样
try {
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
if( factory != null){
sqlSession = factory.openSession();// 非自动提交事务
}
return sqlSession;
}
}
实体类就不展示了
具体的测试类如下
@Test
public void testSelectStudents(){
/**
* 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
* getMapper能获取dao接口对于的实现类对象。
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println("dao="+dao.getClass().getName());
//调用dao的方法, 执行数据库的操作
List<Student> students = dao.selectStudents();
for(Student stu: students){
System.out.println("学生="+stu);
}
}
代码执行还是可以成功执行
通过debug来测试代码如何执行
2. 原理剖析
动态代理:
-
mybatis创建dao接口的实现类,在实现类中调用sqlsession方法执行sql语句
-
getmapper创建对象的时候本身就是一个jdk动态代理方式,com.sun.proxy.$Proxy2 : jdk的动态代理
newProxyInstance的第三个参数即为代理执行器的handler了
最后执行的代码部分是
本身是invoke模块
mapperMethod.execute(this.sqlSession,args)
该方法的invoke的原型是public Object invoke(Object proxy, Method method, Object[] args)。
参数:
Object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的
具体的相关参数
可以参考我之前写的文章
jdk动态代理(AOP)从入门到精通(全)
也可以通过更加深入了解mybatis的相关知识
Mybatis从入门到精通(全)