Mybatis插件原理

 插件原理

     * 在四大对象创建的时候
     * 1、每个创建出来的对象不是直接返回的,而是
     *      interceptorChain.pluginAll( parameterHandler )
     *
     * 2、获取到所有的interceptor(基于拦截器原理)(插件需要实现的接口)
     *      调用所有的Interceptor.pluginAll(target);返回target包装后的对象
     * 3、插件机制,我们可以使用插件为目标对象创建一个代理对象:AOP(面向切面的方式)
     *      我们的插件可以为四大对象创建出代理对象
     *      代理对象就可以拦截到四大对象的每一个执行方法

public Object pluginAll(Object target){
    for (Interceptor interceptor:interceptors) {
        target = interceptor.plugin(target);
    }
    return target;
}

插件编写:

1、编写Interceptor的实现类

2、使用@Intercepts注解完成插件签名

/**
 * 完成了插件签名:告诉mybatis当前插件用来拦截哪个对象的哪个方法
 */
@Intercepts({
        @Signature(type = StatementHandler.class,method = "parameterize",args = java.sql.Statement.class)
})
public class MyFirstPlugin implements Interceptor {
    /**
     * intercept:拦截
     *      拦截目标对象的方法的执行
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("MyFirstPlugin....interceptor:"+invocation.getMethod());
        //执行目标方法
        Object proceed = invocation.proceed();
        //返回执行后的返回值
        return proceed;
    }

    /**
     * plugin:包装目标对象——包装:为目标对象创建一个代理类
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        System.out.println("MyFirstPlugin....plugin:mybatis将要包装的对象"+target);
        //我们可以借助Plugin的wrap方法来使用当前的intercept包装我们目标对象
        Object wrap = Plugin.wrap(target, this);
        //返回为当前target创建好的动态代理
        return wrap;
    }

    /**
     * setProperties:将插件注册时的property属性设置进来
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        System.out.println("插件配置的信息"+properties);
    }
}


3、将写好的插件注册到全局配置文件中

<!--
注册插件
interceptor:插件的全类名
-->
<plugins>
    <plugin interceptor="dao.MyFirstPlugin">
        <!--一下属性会被插件的属性包装-->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </plugin>
</plugins>

运行结果:



多个插件运行原理

@Intercepts(
     {
        @Signature(type = StatementHandler.class,method = "parameterize",args = java.sql.Statement.class)
     }
)
public class MySecondPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("MySecondPlugin.....interceptor"+invocation.getMethod());
        Object proceed = invocation.proceed();
        return proceed;
    }

    @Override
    public Object plugin(Object o) {
        System.out.println("MySecondPlugin.....plugin"+o);
        return Plugin.wrap(o,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
<plugins>
    <plugin interceptor="dao.MyFirstPlugin">
        <!--一下属性会被插件的属性包装-->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </plugin>
    <plugin interceptor="dao.MySecondPlugin"></plugin>
</plugins>


多个插件就会产生多层代理

创建动态代理的时候是按照插件配置顺序创建层层动态代理对象,执行目标方法的时候是按照逆序来的




posted @ 2018-05-26 11:10  惶者  阅读(354)  评论(0编辑  收藏  举报