InvocationHandler
InvocationHandler
接口是 Java 动态代理的核心部分,它里面有一个方法 invoke
当使用动态代理创建一个代理对象时,所有对代理对象的方法调用都会被路由到实现了 InvocationHandler
接口的 invoke
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else { return "你的被代理了!" + sqlSession.get(mapperInterface.getName() + "." + method.getName()); } } }
|
如果创建了一个 MapperProxy
代理对象,那么就会调用 invoke
方法
invoke
方法里,它做了一些判断,对于 Object
类里的方法,不进行代理
Proxy.newProxyInstanse
是 Java 中用于创建动态代理对象的一个静态方法,参数列表如下
1 2
| public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
|
ClassLoader loade
r:指定类加载器,通常传入目标对象的类加载器
Class<?>[] interfaces
:接口数组,代理类会实现这些接口,这些接口决定了代理类可以调用的方法
InvocationHandler h
: 一个接口,代理对象上的所有方法调用都会委托给它的 invoke
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; }
public T newInstance(Map<String, String> sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface); return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy); }
}
|
这个工厂类需要传入一个接口 mapperInterface
,这个接口就是要代理的接口
调用 Proxy.newProxyInstance
方法,传入类加载器,要实现的接口,实现了 InvovationHandler
的接口
1 2 3 4 5 6 7 8 9 10 11 12 13
| mybatis-step-01 └── src ├── main │ └── java │ └── cn.bugstack.mybatis.binding │ ├── MapperProxy.java │ └── MapperProxyFactory.java └── test └── java └── cn.bugstack.mybatis.test.dao ├── dao │ └── IUserDao.java └── ApiTest.java
|
MapperProxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private Map<String, String> sqlSession; private final Class<T> mapperInterface;
public MapperProxy(Map<String, String> sqlSession, Class<T> mapperInterface) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else { return "你的被代理了!" + sqlSession.get(mapperInterface.getName() + "." + method.getName()); } }
}
|
MapperProxyFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; }
public T newInstance(Map<String, String> sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface); return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy); }
}
|
IUserDao
1 2 3 4 5 6 7 8
| public interface IUserDao {
String queryUserName(String uId);
Integer queryUserAge(String uId);
}
|
测试用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Test public void test_MapperProxyFactory() { MapperProxyFactory<IUserDao> factory = new MapperProxyFactory<>(IUserDao.class); Map<String, String> sqlSession = new HashMap<>();
sqlSession.put("cn.bugstack.mybatis.test.dao.IUserDao.queryUserName", "模拟执行 Mapper.xml 中 SQL 语句的操作:查询用户姓名"); sqlSession.put("cn.bugstack.mybatis.test.dao.IUserDao.queryUserAge", "模拟执行 Mapper.xml 中 SQL 语句的操作:查询用户年龄"); IUserDao userDao = factory.newInstance(sqlSession);
String res = userDao.queryUserName("10001"); logger.info("测试结果:{}", res); }
|
本篇文章是在小傅哥的基础上,添加了自己的理解写下的
小傅哥博客:https://bugstack.cn