【MyBatis】动态代理机制

思想 MyBatis中封装了SqlSession来执行具体的JDBC操作,在不使用MyBatis提供的动态代理机制的情况下,Dao层需要手动调用SqlSession来实现对数据库的CRUD,会造成代码的相对冗余和重复。
例如(以StudentDao为例,以下如此):

public Student selectOne(int id) { return sqlSession.selectOne("selectOne", id); }

在使用MyBatis提供的动态代理机制后,就可以将Dao层接口化,java底层自动创建的代理对象将会继承指定的某个Dao类生成对应的子类,调用SqlSession,从而实现某个具体的功能点。
获取代理对象,并指定某个操作:
StudentDao dao = SqlSessionUtil.getSqlSession().getMapper(StudentDao.class); dao.selectOne(id);

注意:
代理对象调用方法不需要传递方法的id,方法的id强制为方法名,底层通过反射技术将方法名和解析后的xml文件标签里的id进行匹配从而找到SQL。
代理对象实现原理 代理对象要想调用SqlSession找到对应的方法,需要知道SQL和参数
  • SQL:
    • 在基于xml开发中SQL在StudentMapper.xml中,需要解析xml文件获取。
    • 在基于注解开发中SQL在注解上,需要解析注解获取。
  • 参数:
    • Service层传递
【【MyBatis】动态代理机制】模拟getMapper()方法:
public T getMapper(Class clazz) { // 加载器用来加载类 ClassLoader classLoader = clazz.getClassLoader(); // 代理对象可以同时代理多个类,一般为一个 Class[] classes = new Class[] {clazz}; InvocationHandler handler = new InvocationHandler() { /** * 代理对象调用某个具体方法的途径 * @param proxy 系统创建的代理对象 * @param method 代理执行的具体方法 * @param args 方法执行需要的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { method.invoke(proxy, args); return proxy; } }; // 构建出继承自指定Dao的代理对象 Object mapper = Proxy.newProxyInstance(classLoader, classes, handler); return (T) mapper; }

    推荐阅读