mybatis的源代码解析(3)----------动态代理的使用
在mybatis中,实现我们的mapper的定义一般如下:
public interface UserMapper { /** * 新增用戶 * * @param user * @return * @throws Exception */ public int insertUser(UserBean user) throws Exception; }
使用时,获取如下:
/** * 新增用户 */ private static void insertUser() { SqlSession session = DBTools.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); UserBean user = new UserBean("懿", "1314520", 7000.0); try { mapper.insertUser(user); System.out.println(user.toString()); session.commit(); } catch (Exception e) { e.printStackTrace(); session.rollback(); } }
UserMapper是一个interface,那么是如何生成它的对象呢,原理就是使用了动态代理的功能。session.getMapper返回的是一个MapperProxy。MapperProxy的定义如下:
public class MapperProxy<T> implements InvocationHandler, Serializable { }
DBTools.getSession()返回的是DefaultSqlSession。DefaultSqlSession的getMapper是一个模板函数,
public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }
configuration就是上一篇中讲到configuration类。configuration的getMapper定义如下:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }
MapperRegistry的getMapper的定义如下:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if(mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }
从上一篇的讲解中,可以知道knownMappers存储的就是imterface mapper和其对应的MapperProxyFactory工厂类。
MapperProxyFactory的定义如下:
public class MapperProxyFactory<T> { private final Class<T> mapperInterface; private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap(); public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } public Class<T> getMapperInterface() { return this.mapperInterface; } public Map<Method, MapperMethod> getMethodCache() { return this.methodCache; } protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); } public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); } }
MapperProxyFactory的newInstance生成了一个MapperProxy 动态代理对象,对于动态代理,其中必须要包含一个实现了interface的实现类,才能运行成功,在mybratis中,Mapper的动态代理包含的实现类都是SqlSession的子类,默认是DefaultSqlSession。
MapperProxy的定义如下:
public class MapperProxy<T> implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession;------------mapper interface最终要调用的实现类 private final Class<T> mapperInterface;--------mapper interface的类 private final Map<Method, MapperMethod> methodCache; public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if(Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } if(this.isDefaultMethod(method)) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); } private MapperMethod cachedMapperMethod(Method method) { MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method); if(mapperMethod == null) { mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration()); this.methodCache.put(method, mapperMethod); } return mapperMethod; } @UsesJava7 private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable { Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(new Class[]{Class.class, Integer.TYPE}); if(!constructor.isAccessible()) { constructor.setAccessible(true); } Class<?> declaringClass = method.getDeclaringClass(); return ((Lookup)constructor.newInstance(new Object[]{declaringClass, Integer.valueOf(2)})).unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args); } private boolean isDefaultMethod(Method method) { return (method.getModifiers() & 1033) == 1 && method.getDeclaringClass().isInterface(); } }
当调用mapper.insertUser(user);函数时,就会进入到MapperProxy的invoke函数

浙公网安备 33010602011771号