sql执行流
mapper 动态代理
简单摘要一下mybatis,mapper接口到方法执行的代理实现
- 模拟几个注解 Insert Update Select
package test.myproxy.mockframework;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Insert {
public abstract String[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
public abstract String[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Update {
public abstract String[] value();
}
- 动态代理
- 1.MapperProxy
public class MapperProxy implements InvocationHandler {
private String method;
private Class target;
private String methodType;
private String sql;
public static <T> T newMapperProxy(Class<T> mapperInterface) {
ClassLoader classLoader = mapperInterface.getClassLoader();
Class[] interfaces = new Class[]{mapperInterface};
MapperProxy proxy = new MapperProxy();
return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
}
private String judgeMethodType(Method method) {
String[] value = method.getAnnotation(Insert.class).value();
if(method.isAnnotationPresent(Insert.class))
{
sql = value[0];
return methodType="insert";
}else if(method.isAnnotationPresent(Update.class))
{
sql = value[0];
return methodType="update";
}else if(method.isAnnotationPresent(Select.class))
{
sql = value[0];
return methodType="select";
}
return null;
}
@Override
public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
System.out.println(" =====被代理了====此处可以做些aop类的事情=====");
judgeMethodType(method);
if(null==methodType)
{
System.out.println("unknow method drop this process");
return null;
}
MapperMethod mapperMethod = new MapperMethod(sql);
mapperMethod.execute(methodType);
System.out.println(" =====代理执行结束=====");
return null;
}
}
- 2.MapperMethod
public class MapperMethod {
private String sql;
public MapperMethod() {
}
public MapperMethod(String sql) {
this.sql = sql;
}
/**
* @param methodType
* @return
*/
public Object execute(String methodType) {
if (null != sql) {
System.out.println("SQL:::" + sql);
}
if ("insert".equals(methodType)) {
System.out.println("insert 获取sql和参数,合成sql 交给下游executor执行");
} else if ("update".equals(methodType)) {
System.out.println("update 获取sql和参数,合成sql 交给下游executor执行");
} else if ("delete".equals(methodType)) {
System.out.println("delete 获取sql和参数,合成sql 交给下游executor执行");
} else {
System.out.println("unkonw method type");
}
return null;
}
}
- 3.SqlSession
public class SqlSession {
public <T> T getMapper(Class<T> clz){
return MapperProxy.newMapperProxy(clz);
}
}
- 4.mapper
public interface BlogMapper {
void delete();
@Insert("insert into mytable")
void insert();
void update();
}
- 5.Test
public class MyTestCase {
@Test
public void myTest() {
SqlSession sqlSession = new SqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
blogMapper.insert();
}
}
- 6.输出
=====被代理了====此处可以做些aop类的事情=====
SQL:::insert into mytable
insert 获取sql和参数,合成sql 交给下游executor执行
=====代理执行结束=====
上述代码纯属摘要模拟,不考虑鲁棒、安全和优雅
小结
- 看码过程中,mybatis作者更加喜欢构造函数构建对象,和spring的setter注入主张各有千秋
- 标准的动态代理,通过封装方法,使用更简单
代码中还是有很多宝贝的,慢慢系统性的挖掘一下 😃