I have two interceptors (PaginationInterceptor and DynamicSqlInterceptor). Both of them intecept below.

@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class}
)})

They have been deployd in this order.

<plugins>
    <plugin interceptor="com.xxx.PaginationInterceptor">
        <property name="start" value="start" />
        <property name="limit" value="limit" />
    </plugin>
    <plugin interceptor="com.xxx.DynamicSqlInterceptor"/>
</plugins>

The purpose of the two interceptors is add page sql and add condition sql.

e.g.

origin sql is

select * from foo_table where 1=1

process by PaginationInterceptor

select * from foo_table where 1=1 limit #start#, #limit#

process by DynamicSqlInterceptor

select * from foo_table where 1=1 and bar = #bar# limit #start#, #limit#

So the two interceptors both want to modify the sql. And they both need to get RoutingStatementHandler

RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
BoundSql boundSql = handler.getBoundSql();

But I found the cast in DynamicSqlInterceptor meet a cast exception. Then I got the reason is because of

InterceptorChain.java
public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
}
PaginationInterceptor.java & DynamicSqlInterceptor.java
public Object plugin(Object target) {
    return Plugin.wrap(target, this);
}

This means I have to code in DynamicSqlInterceptor.intecept like this

Proxy proxy = (Proxy) invocation.getTarget();
Plugin plugin = (Plugin)Proxy.getInvocationHandler(proxy);
Field targetFiled = plugin.getClass().getDeclaredField("target");
targetFiled.setAccessible(true);
Object target = targetFiled.get(plugin);
RoutingStatementHandler handler = (RoutingStatementHandler) target;

And actually in my logic i need the mappedStatement.getId()

public Object intercept(Invocation invocation) throws Throwable {
    Proxy proxy = (Proxy) invocation.getTarget();
    Plugin plugin = (Plugin)Proxy.getInvocationHandler(proxy);
    Field targetFiled = plugin.getClass().getDeclaredField("target");
    targetFiled.setAccessible(true);
    Object target = targetFiled.get(plugin);
    RoutingStatementHandler handler = (RoutingStatementHandler) target;
    Field delegateField = handler.getClass().getDeclaredField("delegate");
    delegateField.setAccessible(true);
    StatementHandler delegateStatementHandler = (StatementHandler) delegateField.get(handler);
    if(delegateStatementHandler instanceof PreparedStatementHandler){
        PreparedStatementHandler delegatePreparedStatementHandler = (PreparedStatementHandler)delegateStatementHandler;
        Field mappedStatementField = delegatePreparedStatementHandler.getClass().getSuperclass().getDeclaredField("mappedStatement");
        mappedStatementField.setAccessible(true);
        MappedStatement mappedStatement = (MappedStatement) mappedStatementField.get(delegatePreparedStatementHandler);
        String serviceMethod = mappedStatement.getId();
        System.out.println(serviceMethod);
    }
    return invocation.proceed();
}

Is there a simple way to do so ? Thanks

Comment From: findxyz

Oh, i am using the below edition

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.7</version>
</dependency>

Comment From: qixiaobo

So sad~Never!!!!Or Maybe you can use MetaObject just like

      MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
    RowBounds rowBounds = (RowBounds)metaStatementHandler.getValue("delegate.rowBounds");