MyBatis操作数据库使用Mapper接口和XML SQL定义并没有创建接口实现类MyBatis如何为Mapper接口生成代理对象的MyBatis使用JDK proxy或Cglib生成一个代理对象在org.apache.ibatis.session.SqlSession方法中扫描Mapper和XML完成对数据库操作。本例通过两种方式演示MyBatis生成代理工作原理一是按照MyBatis规范设计Mapper接口和XML定义自定义代理生成类MapperProxy使用SqlSession触发方法。TestMapper.xml?xml version1.0encodingUTF-8?!DOCTYPEmapperPUBLIC-//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.hk.mapper.TestMapperresultMap idUserMaptypecom.hk.entity.UserInforesult columnidpropertyid/result columnnamepropertyname/result columnlogin_idpropertyloginId/result columnpwdpropertypwd/result columnversionpropertyversion/result columnstatuspropertystatus/result columnorg_namepropertyorgName//resultMapselect idgetUserListparameterTypeStringresultTypecom.hk.entity.UserInfoselect u.* from user u/select/mapperTestMapper.javapackagecom.hk.mybatis;importcom.baomidou.mybatisplus.core.conditions.Wrapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.core.toolkit.Constants;importcom.hk.entity.UserInfo;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;importjava.util.List;publicinterfaceTestMapperextendsBaseMapperUserInfo{publicListUserInfogetUserList();publicListUserInfogetUserByName(Param(name)Stringname);}MapperProxy.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.io.Serializable;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.sql.*;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassMapperProxyTimplementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID-6424540398559729838L;privateSqlSessionsqlSession;privatefinalClassTmapperInterface;publicMapperProxy(SqlSessionsqlSession,ClassTmapperInterface){this.sqlSessionsqlSession;this.mapperInterfacemapperInterface;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(Object.class.equals(method.getDeclaringClass())){// Object 提供的toString、hashCode等不需要代理执行returnmethod.invoke(this,args);}else{returnsqlSession.selectList(method.getName(),args);// 代理映射最终执行是 SqlSession}}}MapperProxyFactory.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.lang.reflect.Proxy;importjava.util.Map;publicclassMapperProxyFactoryT{privatefinalClassTmapperInterface;publicMapperProxyFactory(ClassTmapperInterface){this.mapperInterfacemapperInterface;}publicTnewInstance(SqlSessionsqlSession){finalMapperProxyTmapperProxynewMapperProxy(sqlSession,mapperInterface);// 注意接口在扫描时通过ClassScanner.scanPackage()加载为了一个Java类return(T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),newClass[]{mapperInterface},mapperProxy);// 传入类加载器、接口的类对象代理目标类创建 JDK 动态代理对象}}MapperProxyFactoryTest.javapackagecom.hk.mybatis;importcom.hk.Starter;importcom.hk.entity.UserInfo;importcom.hk.mapper.UserMapper;importorg.apache.ibatis.session.SqlSessionFactory;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importjava.util.HashMap;importjava.util.List;importjava.util.Map;RunWith(SpringRunner.class)SpringBootTest(webEnvironmentSpringBootTest.WebEnvironment.RANDOM_PORT,classesStarter.class)publicclassMapperProxyFactoryTest{AutowiredprivateSqlSessionFactorysqlSessionFactory;Testpublicvoidtest_MapperProxyFactory(){MapperProxyFactoryTestMapperfactorynewMapperProxyFactory(TestMapper.class);MapString,StringxmlMapnewHashMap();// 模拟 SqlSessionTestMapperuserDaofactory.newInstance(sqlSessionFactory.openSession());ListUserInfolistuserDao.getUserList();System.out.println(list);}}二是模拟代理类自定义SQL操作绕开SqlSessionMapperProxy.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.io.Serializable;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.sql.*;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassMapperProxyTimplementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID-6424540398559729838L;privateSqlSessionsqlSession;privatefinalClassTmapperInterface;privateMapString,StringxmlMap;publicMapperProxy(SqlSessionsqlSession,ClassTmapperInterface,MapString,StringxmlMap){this.sqlSessionsqlSession;this.mapperInterfacemapperInterface;this.xmlMapxmlMap;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(Object.class.equals(method.getDeclaringClass())){// Object 提供的toString、hashCode等不需要代理执行returnmethod.invoke(this,args);}else{StringsqlxmlMap.get(method.getName());returnexecuteSql(sqlSession.getConnection(),sql);//return sqlSession.selectList(method.getName(), args); // 代理映射最终执行是 SqlSession}}publicObjectexecuteSql(Connectionconn,Stringsql)throwsThrowable{ListrtnnewArrayList();Statementstatconn.createStatement();ResultSetrsstat.executeQuery(sql);ResultSetMetaDatarsmdrs.getMetaData();intcolsrsmd.getColumnCount();while(rs.next()){MapmnewHashMap();for(inti1;icols;i){StringcolNamersmd.getColumnName(i);StringcolValrs.getString(colName);m.put(colName,colVal);}rtn.add(m);}returnrtn.toArray();}}MapperProxyFactory.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.lang.reflect.Proxy;importjava.util.Map;publicclassMapperProxyFactoryT{privatefinalClassTmapperInterface;publicMapperProxyFactory(ClassTmapperInterface){this.mapperInterfacemapperInterface;}publicTnewInstance(SqlSessionsqlSession,MapString,StringxmlMap){finalMapperProxyTmapperProxynewMapperProxy(sqlSession,mapperInterface,xmlMap);// 注意接口在扫描时通过ClassScanner.scanPackage()加载为了一个Java类return(T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),newClass[]{mapperInterface},mapperProxy);// 传入类加载器、接口的类对象代理目标类创建 JDK 动态代理对象}}TestMapper.javapackagecom.hk.mybatis;importcom.baomidou.mybatisplus.core.conditions.Wrapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.core.toolkit.Constants;importcom.hk.entity.UserInfo;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;importjava.util.List;publicinterfaceTestMapperextendsBaseMapperUserInfo{publicObjectgetUserList();publicObjectgetUserByName(Param(name)Stringname);}MapperProxyFactoryTest.javapackagecom.hk.mybatis;importcom.hk.Starter;importcom.hk.entity.UserInfo;importcom.hk.mapper.UserMapper;importorg.apache.ibatis.session.SqlSessionFactory;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importjava.util.HashMap;importjava.util.List;importjava.util.Map;RunWith(SpringRunner.class)SpringBootTest(webEnvironmentSpringBootTest.WebEnvironment.RANDOM_PORT,classesStarter.class)publicclassMapperProxyFactoryTest{AutowiredprivateSqlSessionFactorysqlSessionFactory;Testpublicvoidtest_MapperProxyFactory(){MapperProxyFactoryTestMapperfactorynewMapperProxyFactory(TestMapper.class);MapString,StringxmlMapnewHashMap();// 模拟 SqlSessionxmlMap.put(getUserList,select u.* from user u);xmlMap.put(getUserByLoginId,模拟执行 Mapper.xml 中 SQL 语句的操作查询用户信息);TestMapperuserDaofactory.newInstance(sqlSessionFactory.openSession(),xmlMap);ObjectobjuserDao.getUserList();Object[]userDim(Object[])obj;for(introw0;rowuserDim.length;row){Mapmap(Map)userDim[row];System.out.println(map);}}}