给自己的每日一句
不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽都顺利。
如何找到孙帅本人
本文内容整理自《孙哥说Mybatis系列视频课程》,老师实力十分雄厚,B站搜孙帅可以找到本人,视频中有老师的微信号。
前言
拦截器并不是简单对Dao层对象进行拦截,而是更加偏向底层的拦截,拦截的是Executor和各种Handler。
在这四个里边,最终要的是Executor和StatementHandler,当然最常用的是StatementHandler因为它是与数据库实际交互的,更加底层。
我们真正在StatementHandler开启的任务是拦截操作,拦截器的就是增删改查的处理,是通过StatementHandler其中的两个方法体现的,query和update方法
如果我们方法都要拦截,最好我们直接拦截prepare方法,因为他有两个好处,一个是prepare在update和query方法执行前执行,返回值是statement。另一个是prepare方法中的入参中有connection对象。所有JDBC的操作都是基于Connection,有了连接我们就有了一切。
一:拦截器获取拦截对象
答案是在intercepter方法当中:
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class MyMybatisInterceptor3 extends MyMybatisInterceptorAdapter { private static final Logger log = LoggerFactory.getLogger(MyMybatisInterceptor3.class); @Override public Object intercept(Invocation invocation) throws Throwable { if (log.isDebugEnabled()) log.debug("-----this is myMybatisInterceptor3-------"); MetaObject metaObject = SystemMetaObject.forObject(invocation); String methodName = (String) metaObject.getValue("method.name"); String sql = (String) metaObject.getValue("target.delegate.boundSql.sql"); if (log.isDebugEnabled()) log.debug("methodname is " + methodName + " sql is " + sql); return invocation.proceed(); } @Override public void setProperties(Properties properties) { } }
Invocation 对象源码
public class Invocation { private final Object target; private final Method method; private final Object[] args; public Invocation(Object target, Method method, Object[] args) { this.target = target; this.method = method; this.args = args; } public Object getTarget() { return target; } public Method getMethod() { return method; } public Object[] getArgs() { return args; } public Object proceed() throws InvocationTargetException, IllegalAccessException { return method.invoke(target, args); } }
Invocation对象里边有一个target对象,代表的就是拦截器所拦截的目标
method所代表的就是我们拦截的方法。当前案例中对饮的就是prepare方法
Object[] args这个数据,代表的就是拦截方法的参数。
1:如果获取被拦截方法和参数
2:演示证明
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class MyMybatisInterceptor3 extends MyMybatisInterceptorAdapter { private static final Logger log = LoggerFactory.getLogger(MyMybatisInterceptor3.class); @Override public Object intercept(Invocation invocation) throws Throwable { if (log.isDebugEnabled()) log.debug("-----this is myMybatisInterceptor3-------"); MetaObject metaObject = SystemMetaObject.forObject(invocation); String methodName = (String) metaObject.getValue("method.name"); String sql = (String) metaObject.getValue("target.delegate.boundSql.sql"); if (log.isDebugEnabled()) log.debug("methodname is " + methodName + " sql is " + sql); return invocation.proceed(); } @Override public void setProperties(Properties properties) { } }
<plugins> <plugin interceptor="com.baizhiedu.plugins.MyMybatisInterceptor3"/> </plugins>
二:MetaObject
1:MetaObject简介
Mybatis封装的反射,进行导航式的数据取值与赋值。整个过程都是基于反射完成,十分简化开发。
MetaObject metaObject = SystemMetaObject.forObject(invocation); String methodName = (String) metaObject.getValue("method.name"); String sql = (String) metaObject.getValue("target.delegate.boundSql.sql"); log.debug("methodname is " + methodName + " sql is " + sql);
2:MetaObject代码展示
package org.apache.ibatis.reflection; public class MetaObject { private final Object originalObject; private final ObjectWrapper objectWrapper; private final ObjectFactory objectFactory; private final ObjectWrapperFactory objectWrapperFactory; private final ReflectorFactory reflectorFactory; private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { this.originalObject = object; this.objectFactory = objectFactory; this.objectWrapperFactory = objectWrapperFactory; this.reflectorFactory = reflectorFactory; if (object instanceof ObjectWrapper) { this.objectWrapper = (ObjectWrapper) object; } else if (objectWrapperFactory.hasWrapperFor(object)) { this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object); } else if (object instanceof Map) { this.objectWrapper = new MapWrapper(this, (Map) object); } else if (object instanceof Collection) { this.objectWrapper = new CollectionWrapper(this, (Collection) object); } else { this.objectWrapper = new BeanWrapper(this, object); } }
但凡是开发源框架,底层都会进行基本的封装:IO,反射,集合的操作都会进行封装。
三:如何使用Mybatis拦截器解决开发中的实际问题
在Mybatis开发中可能要
1:对SQL语句进行操作。
2:分页
3:乐观锁
在接下来的文章中,我们会对着实际开发中的三个问题,进行详细的说明。