先抛出一个问题,用过Mybatis的都知道,我们只需要定义一个Dao的接口,在里面写上一些CRUD相关操作,然后配置一下sql映射文件,就可以达到调用接口中的方法,然后执行sql语句的效果,为什么呢?我们并没有具体的CRUD操作的实现类啊?
前面说到得到SqlSessionFactory对象,得到SqlSessionFactory是为了得到sqlSession,。SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法。你可以用SqlSession实例来直接执行已映射的SQL语句。
String configure = "com/mybatis/test/mybatis-configure.xml";
InputStream res = SqlSessionTest.class.getClassLoader().getResourceAsStream(configure);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(res);
SqlSession session = ssf.openSession();
AuthUserDao mapper = session.getMapper(AuthUserDao.class);
AuthUser authUser = mapper.selectAuthUserByName("root");
我们通过SqlSession session = ssf.openSession(); 得到SqlSession之后,就可以用来执行配置在映射文件的sql了。
上面的代码中通过 session.getMapper(AuthUserDao.class) 来加载sql映射文件中的sql语句。并且执行这些sql语句。往里面看代码,开头的答案揭晓了,这就是Java动态代理类。
先介绍一下java提供一种动态代理类。可以实现类似于AOP之类的思想,就是在我们执行某个接口之前,同时执行我们相关的代码。一个简单的例子就是我们在执行某个接口之前,打印日志。下面是写的一个简单的例子。
DynaProxyHandler.java:
/**
*
* @author yinzi.zhu_C
*/
public class DynaProxyHandler implements InvocationHandler{
private Object target;
public DynaProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("模拟打印日志");
return method.invoke(target, args);
}
}
ProxyFactory.java
public static Object getProxy(Object target){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new DynaProxyHandler(target));
}
IPerson、 personImpl分别为接口和实现类。只有一个speak(String msg)方法。
ProxyTest.java
public class ProxyTest {
public static void main(String[] args) {
DynaProxyHandler handler = new DynaProxyHandler(new PersonImpl());
IPerson person = (IPerson) ProxyFactory.getProxy(new PersonImpl());
person.speak("Hello world");
}
}
运行结果为:
模拟打印日志!
person speak: Hello world
看,这就是Java当中的动态代理类,我们只需要实现InvocationHandler接口。然后当我们执行目标类的方法时,掺杂上我们要做的事情。实现类似AOP的效果。
回到Mybatis,其实Mybatis也是通过代理类来实现我们只执行接口当中的方法,就达到执行sql映射文件中的sql语句的效果。