给自己的每日一句
不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽都顺利。
如何找到孙帅本人
本文内容整理自《孙哥说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:乐观锁
在接下来的文章中,我们会对着实际开发中的三个问题,进行详细的说明。