app开发者平台在数字化时代的重要性与发展趋势解析
726
2022-10-30
MyBatis从入门到精通—MyBatis插件原理探究和自定义插件实现
插件简介
⼀般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者⾃⾏拓展。这样的好处是显⽽易⻅的,⼀是增加了框架的灵活性。⼆是开发者可以结合实际需求,对框架进⾏拓展,使其能够更好的⼯作。以MyBatis为例,我们可基于MyBati s插件机制实现分⻚、分表,监控等功能。由于插件和业务⽆关,业务也⽆法感知插件的存在。因此可以⽆感植⼊插件,在⽆形中增强功能。
Mybatis插件介绍
Mybati s作为⼀个应⽤⼴泛的优秀的ORM开源框架,这个框架具有强⼤的灵活性,在四⼤组件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易⽤的插 件扩展机制。Mybatis对持久层的操作就是借助于四⼤核⼼对象。MyBatis⽀持⽤插件对四⼤核⼼对象进⾏拦截,对mybatis来说插件就是-,⽤来增强核⼼对象的功能,增强功能本质上是借助于底层的 动态代理实现的,换句话说,MyBatis中的四⼤对象都是代理对象。MyBatis所允许拦截的⽅法如下:
执⾏器Executor (update、query、commit、rollback等⽅法); SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等⽅ 法); 参数处理器ParameterHandler (getParameterObject、setParameters⽅法); 结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等⽅法); Mybatis插件原理 在四⼤对象创建的时候
每个创建出来的对象不是直接返回的,⽽是interceptorChain.pluginAll(parameterHandler); 获取到所有的Interceptor (-)(插件需要实现的接⼝);调⽤ interceptor.plugin(target);返回 target 包装后的对象 插件机制,我们可以使⽤插件为⽬标对象创建⼀个代理对象;AOP (⾯向切⾯)我们的插件可以为四⼤对象创建出代理对象,代理对象就可以拦截到四⼤对象的每⼀个执⾏;
拦截插件具体是如何拦截并附加额外的功能的呢?以ParameterHandler来说。
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object object, BoundSql sql, InterceptorChain interceptorChain){ ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql); parameterHandler = (ParameterHandler)interceptorChain.pluginAll(parameterHandler); return parameterHandler; } public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; }
interceptorChain保存了所有的-(interceptors),是mybatis初始化的时候创建的。调⽤-链中的-依次的对⽬标进⾏拦截或增强。interceptor.plugin(target)中的target就可以理解为mybatis中的四⼤对象。返回的target是被重重代理后的对象如果我们想要拦截Executor的query⽅法,那么可以这样定义插件:
@Intercepts({ @Signature( type = Executor.class, method = "query", args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class} ) }) public class ExeunplePlugin implements Interceptor { //省略逻辑 }
除此之外,我们还需将插件配置到sqlMapConfig.xml中。
这样MyBatis在启动时可以加载插件,并保存插件实例到相关对象(InterceptorChain,-链) 中。待准备⼯作做完后,MyBatis处于就绪状态。我们在执⾏SQL时,需要先通过DefaultSqlSessionFactory创建 SqlSession。Executor 实例会在创建 SqlSession 的过程中被创建, Executor实例创建完毕后,MyBatis会通过JDK动态代理为实例⽣成代理类。这样,插件逻辑即可在 Executor相关⽅法被调⽤前执⾏。以上就是MyBatis插件机制的基本原理。
⾃定义插件
插件接口
Mybatis 插件接⼝-Interceptor
Intercept⽅法,插件的核⼼⽅法
plugin⽅法,⽣成target的代理对象
setProperties⽅法,传递插件所需参数
⾃定义插件
设计实现⼀个⾃定义插件
Intercepts ({//注意看这个⼤花括号,也就这说这⾥可以定义多个@Signature对多个地⽅拦截,都⽤这个-
@Signature (type = StatementHandler .class , //这是指拦截哪个接⼝
method = "prepare",//这个接⼝内的哪个⽅法名,不要拼错了
args = { Connection.class, Integer .class}),//// 这是拦截的⽅法的⼊参,按顺序写到这,不要多也不要少,如果⽅法重载,可是要通过⽅法名和⼊参来确定唯⼀的
})
public class MyPlugin implements Interceptor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// //这⾥是每次执⾏操作的时候,都会进⾏这个-的⽅法内
@Override
public Object intercept(Invocation invocation) throws Throwable {
//增强逻辑
System.out.println("对⽅法进⾏了增强....");
return invocation.proceed(); //执⾏原⽅法
}
/**
* //主要是为了把这个-⽣成⼀个代理放到-链中
* ^Description包装⽬标对象 为⽬标对象创建代理对象
* @Param target为要拦截的对象
* @Return代理对象
*/
@Override
public Object plugin(Object target) {
System.out.println("将要包装的⽬标对象:"+target);
return Plugin.wrap(target,this);
}
/**获取配置⽂件的属性**/
//插件初始化的时候调⽤,也只调⽤⼀次,插件配置的属性从这⾥设置进来
@Override
public void setProperties(Properties properties) {
System.out.println("插件配置的初始化参数:"+properties );
}
}
sqlMapConfig.xml
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~