插件原理

插件简介

一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作。以MyBatis为例,我们可基于MyBati s插件机制实现分页、分表,监控等功能。由于插件和业务 无关,业务也无法感知插件的存在。因此可以无感植入插件,在无形中增强功能

Mybati s作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插 件扩展机制。Mybatis对持久层的操作就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进 行拦截,对mybatis来说插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的 动态代理实现的,换句话说,MyBatis中的四大对象都是代理对象

l四大拦截对象

允许拦截的方法如下:

执行器Executor (update、query、commit、rollback等方法);

SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方 法);

参数处理器ParameterHandler (getParameterObject、setParameters方法);

结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法);

Mybatis插件原理

在四大对象创建的时候

1、每个创建出来的对象不是直接返回的,而是interceptorChain.pluginAll(parameterHandler);

2、获取到所有的Interceptor (拦截器)(插件需要实现的接口);调用 interceptor.plugin(target);返回 target 包装后的对象

3、插件机制,我们可以使用插件为目标对象创建一个代理对象;AOP (面向切面)我们的插件可 以

为四大对象创建出代理对象,代理对象就可以拦截到四大对象的每一个执行;


自定义插件实现

@Intercepts({

@Signature(type= Executor.class,

                  method ="query",

                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})

})

public class MyPlugin1implements Interceptor {

/*

        拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法*/

    @Override

    public Objectintercept(Invocation invocation)throws Throwable {

System.out.println("对方法进行了增强....");

        //原方法参数

        Object[] args = invocation.getArgs();

        //原方法

        Method method = invocation.getMethod();

        //目标对象

        Object target = invocation.getTarget();

        //这里我们将原来查询的1 改为3

        Integer u=  (Integer) args[1];

        args[1]=3;

        System.out.println(u);

        return invocation.proceed(); //原方法执行

    }

/*

      主要为了把当前的拦截器生成代理存到拦截器链中*/

    @Override

    public Objectplugin(Object target) {

Object wrap = Plugin.wrap(target, this);

        return wrap;

    }

/*

        获取配置文件的参数*/

    @Override

    public void setProperties(Properties properties) {

System.out.println("获取到的配置文件的参数是:"+properties);

    }

}


配置文件:

配置自定义插件\

测试结果如下:

测试结果

源码分析

Plugin实现了InvocationHandler接口 所以最终执行的实际上是invoke方法:

invoke方法

4,在每次创建excutor时候

拦截器执行


代理放入拦截器链

你可能感兴趣的:(插件原理)