首页 新闻 会员 周边

MyBatis中使用多个插件时,分离代理对象链为何不行

0
悬赏园豆:50 [待解决问题]

首先定义两个插件MyPlugin和MyPlugin2。都采用分离代理对象链的方式处理。因为后配置MyPlugin2所以先进行Myplugin2。两个插件代码几乎一样。问题来了,

statementHandler = (StatementHandler)object;
是第一次错误的位置报
org.apache.ibatis.plugin.Plugin cannot be cast to org.apache.ibatis.executor.statement.StatementHandler
去掉该行之后

String sql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");报错</font>There is no getter for property named 'delegate' in 'class org.apache.ibatis.plugin.Plugin'

我想知道多个插件不能分离代理对象操作吗?

插件配置:

<plugin interceptor="com.ssm.chapter8.plugin.MyPlugin">
            <property name="dbType" value="mysql"/>
</plugin>
<plugin interceptor="com.ssm.chapter8.plugin.MyPlugin2">
            <property name="dbType" value="mysql2"/>
</plugin>

MyPlugin的intercept方法:

public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        //进行绑定
    MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
    Object object = null;
        /*分离代理对象链(由于目标类可能被多个拦截器[插件]拦截,从而形成多次代理,通过循环可以分离出最原始的目标类)*/
    while(metaStatementHandler.hasGetter("h")){
        object = metaStatementHandler.getValue("h");
        metaStatementHandler = SystemMetaObject.forObject(object);
        }

statementHandler = (StatementHandler)object;String sql = (String)metaStatementHandler.getValue("delegate.boundSql.sql")
    Long parameterObject = (Long)metaStatementHandler.getValue("delegate.boundSql.parameterObject");
        
    log.info("执行的SQL:【"+sql+"】");
    log.info("before......");
        //如果当前代理的事一个非代理对象,那么它就会回调用真实拦截对象的方法
        //如果不是,那么它就会调度下一个插件代理对象的invoke方法
    Object obj = invocation.proceed();
    log.info("after......");
    return obj;
}

MyPlugin2的intercept方法:

public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        //进行绑定
        MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
        Object object = null;
        /*分离代理对象链(由于目标类可能被多个拦截器[插件]拦截,从而形成多次代理,通过循环可以分离出最原始的目标类)*/
        while(metaStatementHandler.hasGetter("h")){
            object = metaStatementHandler.getValue("h");
            metaStatementHandler = SystemMetaObject.forObject(object);
        }
        statementHandler = (StatementHandler)object;
        String sql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");
        Long parameterObject = (Long)metaStatementHandler.getValue("delegate.boundSql.parameterObject");
        
        log.info("Myplugin2执行的SQL:【"+sql+"】");
        log.info("Myplugin2参数:【"+parameterObject+"】");
        log.info("Myplugin2before......");
        //如果当前代理的事一个非代理对象,那么它就会回调用真实拦截对象的方法
        //如果不是,那么它就会调度下一个插件代理对象的invoke方法
        Object obj = invocation.proceed();
        log.info("Myplugin2after......");
        return obj;
    }
爱打程序的篮球员的主页 爱打程序的篮球员 | 初学一级 | 园豆:152
提问于:2019-01-07 15:30

// 分离最后一个代理对象的目标类
while (metaStatementHandler.hasGetter("target")) {
Object object = metaStatementHandler.getValue("target");
metaStatementHandler = MetaObject.forObject(object, OBJECT_FACTORY, OBJECT_WRAPPER_FACTORY);
}

技术来源于生活 5年前
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册