简单演示springAOP在Mybatis中的使用
Mybatis的getMapper底层就是JDK的动态代理,并且运用了springAOP
外部调用
基于sqlSession使用getMapper(接口 . Class)获得动态代理对象
第一层内置类 DefaultSqlSession.java
此时getMapper会将Class对象和this对象(代指上图的sqlSession)一同传到另一个getMapper中
第二层内置类 Configuration.java
第三层内置类 MapperRegistry.java
进一步进入getMapper 就能来到最终执行的地方
BindingException 用来抛出异常 我们常见的也就是这个异常
传入的SysUserMapper要注册到MapperRegistry上,如果没有注册成功就会抛出这个异常
比如mybatis核心配置文件中没有成功配置SysUserMapper的接口对应的映射文件,就会出这个异常
图中假如没有配置包扫描,使用的是手动配置,然后漏掉了映射文件,就会报这个异常
假如注册成功就会是如下情况
当注册成功后,进一步进入newInstance这个方法
第四层内置类 MapperProxyFactory.java
在这一个类中,会跳转到newInstance方法 这就是JDK的动态代理
在方法的参数表中可以看到 目标对象的类加载器 ,一个新创建的Class数组,一个MapperProxy对象
①目标对象的类加载器
这个东西不是很重要,可以传入任意对象的类加载器,通常传入目标对象,也可以不传,它有默认的ClassLoader()
①Class数组
对应着手写的方法中的getInterfaces() ,这是这里是直接传入了一个指向目标对象的接口的Class对象到数组中,形成一个Class对象数组
之所以是一个数组是因为JAVA存在单继承多接口的情况
②MapperProxy对象
对应着手写的方法中的InvocationHandler(),必须是一个实现了InvocationHandler接口的对象,或者就干脆是一个“new InvocationHandler()”的匿名函数
第五层内置类 MapperProxy.java
通过MapperProxy对象进入这个类,可以看到这个类实现了InvocationHandler接口
手写动态代理方法时,InvocationHandler方法是即时new 即时用 用完就没了 是一个匿名函数
在这里则是由一个有固定名字的类实现了接口,不再以匿名函数的方式使用,并且这个类中肯定有invoke方法,用于执行目标对象中的方法
仔细查看,可以找到这个invoke方法
这个invoke方法会判断method是否来自于object
如果是就不进行增强,比如toString、getClass
执行完毕后就会输出对象
如果不是,则执行增强
源码中代理类实现的接口是一个list集合 因为目标对象可能实现了多个接口