mybatis::SQL执行流和动态代理

sql执行流

image.png

mapper 动态代理

image.png

简单摘要一下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注入主张各有千秋
  • 标准的动态代理,通过封装方法,使用更简单
    代码中还是有很多宝贝的,慢慢系统性的挖掘一下 :)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容