MyBatis的Mapper接口动态代理原理
1、什么是mapper接口的动态代理
创建sqlsession对象
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
不使用动态代理
比如:session.selectList(命名空间.sql的id)
//如果命名空间和使用这个方法的类在同一个包下面,那么这个命名空间可以省略不写
使用动态接口代理
创建mapper接口,这个接口与mapper.xml在同一个包下面:
public interface UserMapper {
List<User> selectList();
}
获取动态mapper对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
通过mapper对象执行接口语句
//使用userMapper就能随便使用接口里面的方法了
userMapper.selectList()
通过上面的例子可以知道,使用sqlsession和命名空间直接执行sql语句的就不是mapper动态接口代理。而动态接口代理是获取mapper接口的代理对象,通过这个对象执行mapper.xml映射文件里面的sql语句
2、mapper接口动态代理的代码实现
2.1假定一个接口
public interface UserMapper{
List<User> selectAll();
}
2.2使用java的动态代理方式,创建一个类
public class MyMapperProxy<T> implements InvocationHandler{
private Class<T> mapperInterface;
private SqlSession sqlsession;
public MyMapperProxy(Class<T> mapperInterface , SqlSession sqlsession){
this.mapperInterface = mapperInterface;
this.sqlSession = sqlSession;
}
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
List<T> list = sqlSession.selectList(mapperInterface.getCanonicalName()+","+method.getName());
return list;
}
}
2.3测试代码
//获取session
SqlSession sqlSession = getSqlSession();
//获取UserMapper接口
MyMapperProxy userMapperProxy = new MyMapperProxy(){UserMapper.class,sqlSession};
//使用动态代理
(UserMapper) Proxy.newProxyInstance{
Thread.getCurrentThread().getContextClassLoader(),
new Class[]{UserMapper.class},
userMapperProxy
};
//调用方法
List<User> users = userMapper.selectAll();