mybatis-plus icon indicating copy to clipboard operation
mybatis-plus copied to clipboard

如果在插件中使用装饰模式增强、并非jdk动态代理时,会导致com.baomidou.mybatisplus.core.toolkit.PluginUtils#realTarget获取实际处理对象失败

Open bugCats opened this issue 9 months ago • 2 comments

如果在插件中使用装饰模式增强、并非jdk动态代理时,会导致com.baomidou.mybatisplus.core.toolkit.PluginUtils#realTarget获取实际处理对象失败

当前使用版本 mybatisplus所有版本

当前环境信息 Java8 + Mysql5.7

描述bug现象 之前使用mybatis,自定义了很多插件,插件使用装饰模式增强,并非JDK动态代理。 最近打算升级到mybatis-plus,发现在com.baomidou.mybatisplus.core.toolkit.PluginUtils#realTarget处报错,此方法并未分离出来实际对象。

提供问题复现步骤

拦截器示例:使用装饰模式增强StatementHandler.prepare

@Component
public class MyInterceptor implements Interceptor {
    
    @Override
    public Object intercept(Invocation invocation) {
        return null;
    }

    @Override
    public Object plugin(Object target) {
        if ( target instanceof StatementHandler ) {
            return new StatementHandlerWrap((StatementHandler) target); //此处只演示StatementHandler,装饰其他对象也会造成同样异常
        }
        return target;
    }

    private static class StatementHandlerWrap implements StatementHandler {
        private final StatementHandler h; //模拟jdk动态代理后的目标对象属性名
        private StatementHandlerWrap(StatementHandler statementHandler) {
            this.h = statementHandler;
        }

        @Override
        public Statement prepare(Connection connection, Integer timeout) throws SQLException {
            //增强代码
            return h.prepare(connection, timeout);
        }

        @Override
        public void parameterize(Statement statement) throws SQLException {
            h.parameterize(statement);
        }
        @Override
        public void batch(Statement statement) throws SQLException {
            h.batch(statement);
        }
        @Override
        public int update(Statement statement) throws SQLException {
            return h.update(statement);
        }
        @Override
        public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
            return h.query(statement, resultHandler);
        }
        @Override
        public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
            return h.queryCursor(statement);
        }
        @Override
        public BoundSql getBoundSql() {
            return h.getBoundSql();
        }
        @Override
        public ParameterHandler getParameterHandler() {
            return h.getParameterHandler();
        }
    }
}

异常信息:

Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'delegate' in 'class xxx.xxx.MyInterceptor$StatementHandlerWrap'
	at org.apache.ibatis.reflection.Reflector.getGetInvoker(Reflector.java:374)
	at org.apache.ibatis.reflection.MetaClass.getGetInvoker(MetaClass.java:164)
	at org.apache.ibatis.reflection.wrapper.BeanWrapper.getBeanProperty(BeanWrapper.java:162)
	at org.apache.ibatis.reflection.wrapper.BeanWrapper.get(BeanWrapper.java:49)
	at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)
	at com.baomidou.mybatisplus.core.toolkit.PluginUtils.mpStatementHandler(PluginUtils.java:72)
	at com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor.beforePrepare(BlockAttackInnerInterceptor.java:53)
	at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:102)
	...

实际原因: com.baomidou.mybatisplus.core.toolkit.PluginUtils#realTarget,只有在入参target是JDK代理对象时,才会执行获取实际对象逻辑。

bugCats avatar May 20 '24 06:05 bugCats