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");