在平时开发中,我们一般使用mybatis是这样的:
创建一个接口(此处暂时忽略mybatis加载配置文件的过程):
@Mapper
public interface UserMapper {
public void update(User user);
}
配置一个XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tongmin.mapper.UserMapper">
<update id="update" parameterType="com.tongmin.entity.User" >
update user
<set >
<if test="userName != null" >
user_name = #{userName,jdbcType=VARCHAR},
</if>
<if test="passWord != null" >
pass_word = #{passWord,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>
接下来在业务中注册UserMapper,然后就直接调用方法update。
到这里,就有一个问题,接口是不能实例化的,那么我们是怎么直接调用接口的方法的呢?
在mybatis中使用了动态代理来解决这个问题,但是mybatis的动态代理又不一样,普通的动态代理是需要有接口实现类,而mybatis的动态代理是不需要接口实现类的。
此处模拟一个动态代理:
创建一个Mapper
public interface RoleMapper {
public void getRole();
}
创建一个InvocationHandler:
public class ProxyInvocationHandler implements InvocationHandler{
public ProxyInvocationHandler(){
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object object = null;
//此处执行具体的业务逻辑,如根据方法名称加载sql语句,
//根据方法名称加载参数,根据方法名称加载返回结果类型
System.out.println("执行具体的业务逻辑");
return object;
}
}
创建一个Mapper工厂:
public class ProxyFactory<T> {
private ProxyInvocationHandler handler;
private Class<T> interfaceName;
public ProxyFactory(ProxyInvocationHandler handler,Class<T> interfaceName) {
this.handler = handler;
this.interfaceName = interfaceName;
}
//创建具体的代理对象
public T getInterface(){
T clazz = (T) Proxy.newProxyInstance(interfaceName.getClassLoader(), new Class[]{interfaceName}, handler);
return clazz;
}
}
具体的测试类:
public class ProxyTest {
public static void main(String[] args) {
ProxyInvocationHandler handler = new ProxyInvocationHandler();
ProxyFactory<RoleMapper> factory = new ProxyFactory<RoleMapper>(handler, RoleMapper.class);
System.out.println(factory.getInterface().getRole());
}
}