一、创建简单的映射器代理工厂
1.设计
在设计实现ORM框架的过程中,首先要考虑怎么把用户定义的数据库操作接口、xml配置的SQL语句、数据库三者联系起来。最合适的操作是使用代理的方式进行处理,因为代理可以封装一个复杂的流程为接口对象的实现类。具体代理类设计如下图:
- 首先提供一个映射器的代理实现类MapperProxy,通过代理类包装对数据库的操作。
- 之后对MapperProxy代理类,提供工厂实例化操作MapperProxyFactory#newInstance,为每一个IDao接口生成代理类。(使用到简单工厂模式)
2.实现
下面就是根据设计实现一个简单的映射器代理操作。使用到代理知识。
Mybatis映射器代理类关系如下图:
- MapperProxy负责实现InvocationHandler接口的invoke方法,最终所有的实际调用都会调用到这个方法包装的逻辑。
- MapperProxyFactory是对MapperProxy的包装,对外提供实例化对象的操作。
2.1 映射器代理类
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object提供的toString、hashCode等方法是不需要代理执行的
// 这个条件检查正在被调用的方法是否是Object类的方法。如果是,说明调用的方法是Object类的
//方法,比如equals、hashCode或toString。
if(Object.class.equals(method.getDeclaringClass())){
return method.invoke(this,args);
}else {
return "你被代理了 !" + sqlSession.get(mapperInterface.getName() + "." + method.getName());
}
}
2.2 代理类工厂
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}