sql執(zhí)行流

image.png
mapper 動態(tài)代理

image.png
簡單摘要一下mybatis,mapper接口到方法執(zhí)行的代理實現(xiàn)
- 模擬幾個注解 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();
}
- 動態(tài)代理
- 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(" =====代理執(zhí)行結束=====");
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和參數(shù),合成sql 交給下游executor執(zhí)行");
} else if ("update".equals(methodType)) {
System.out.println("update 獲取sql和參數(shù),合成sql 交給下游executor執(zhí)行");
} else if ("delete".equals(methodType)) {
System.out.println("delete 獲取sql和參數(shù),合成sql 交給下游executor執(zhí)行");
} 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和參數(shù),合成sql 交給下游executor執(zhí)行
=====代理執(zhí)行結束=====
上述代碼純屬摘要模擬,不考慮魯棒、安全和優(yōu)雅
小結
- 看碼過程中,mybatis作者更加喜歡構造函數(shù)構建對象,和spring的setter注入主張各有千秋
- 標準的動態(tài)代理,通過封裝方法,使用更簡單
代碼中還是有很多寶貝的,慢慢系統(tǒng)性的挖掘一下 :)