浏览代码

优化MapperProxy属性访问.

https://github.com/baomidou/mybatis-plus/issues/6575
nieqiurong 3 月之前
父节点
当前提交
90b6587d0a

+ 18 - 18
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java

@@ -22,9 +22,9 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.enums.SqlMethod;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.MapperProxyMetadata;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
 import org.apache.ibatis.annotations.Param;
@@ -133,9 +133,9 @@ public interface BaseMapper<T> extends Mapper<T> {
                 return this.deleteById(instance);
             }
         }
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
-        SqlSession sqlSession = mybatisMapperProxy.getSqlSession();
-        return sqlSession.delete(mybatisMapperProxy.getMapperInterface().getName() + Constants.DOT + SqlMethod.DELETE_BY_ID.getMethod(), obj);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
+        SqlSession sqlSession = mapperProxyMetadata.getSqlSession();
+        return sqlSession.delete(mapperProxyMetadata.getMapperInterface().getName() + Constants.DOT + SqlMethod.DELETE_BY_ID.getMethod(), obj);
     }
 
     /**
@@ -206,10 +206,10 @@ public interface BaseMapper<T> extends Mapper<T> {
         if (CollectionUtils.isEmpty(collections)) {
             return 0;
         }
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
         Class<?> entityClass = GenericTypeUtils.resolveTypeArguments(getClass(), BaseMapper.class)[0];
-        SqlSession sqlSession = mybatisMapperProxy.getSqlSession();
-        Class<?> mapperInterface = mybatisMapperProxy.getMapperInterface();
+        SqlSession sqlSession = mapperProxyMetadata.getSqlSession();
+        Class<?> mapperInterface = mapperProxyMetadata.getMapperInterface();
         TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
         Map<String, Object> params = new HashMap<>();
         if (useFill && tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill()) {
@@ -505,9 +505,9 @@ public interface BaseMapper<T> extends Mapper<T> {
      * @since 3.5.7
      */
     default List<BatchResult> insert(Collection<T> entityList, int batchSize) {
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
-        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mybatisMapperProxy.getMapperInterface());
-        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
+        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mapperProxyMetadata.getMapperInterface());
+        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mapperProxyMetadata.getSqlSession());
         return MybatisBatchUtils.execute(sqlSessionFactory, entityList, method.insert(), batchSize);
     }
 
@@ -529,9 +529,9 @@ public interface BaseMapper<T> extends Mapper<T> {
      * @since 3.5.7
      */
     default List<BatchResult> updateById(Collection<T> entityList, int batchSize) {
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
-        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mybatisMapperProxy.getMapperInterface());
-        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
+        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mapperProxyMetadata.getMapperInterface());
+        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mapperProxyMetadata.getSqlSession());
         return MybatisBatchUtils.execute(sqlSessionFactory, entityList, method.updateById(), batchSize);
     }
 
@@ -553,11 +553,11 @@ public interface BaseMapper<T> extends Mapper<T> {
      * @since 3.5.7
      */
     default List<BatchResult> insertOrUpdate(Collection<T> entityList, int batchSize) {
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
         Class<?> entityClass = GenericTypeUtils.resolveTypeArguments(getClass(), BaseMapper.class)[0];
         TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
         String keyProperty = tableInfo.getKeyProperty();
-        String statement = mybatisMapperProxy.getMapperInterface().getName() + StringPool.DOT + SqlMethod.SELECT_BY_ID.getMethod();
+        String statement = mapperProxyMetadata.getMapperInterface().getName() + StringPool.DOT + SqlMethod.SELECT_BY_ID.getMethod();
         return insertOrUpdate(entityList, (sqlSession, entity) -> {
             Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
             return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(statement, entity));
@@ -582,9 +582,9 @@ public interface BaseMapper<T> extends Mapper<T> {
      * @since 3.5.7
      */
     default List<BatchResult> insertOrUpdate(Collection<T> entityList, BiPredicate<BatchSqlSession, T> insertPredicate, int batchSize) {
-        MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
-        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mybatisMapperProxy.getMapperInterface());
-        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+        MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this);
+        MybatisBatch.Method<T> method = new MybatisBatch.Method<>(mapperProxyMetadata.getMapperInterface());
+        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mapperProxyMetadata.getSqlSession());
         return MybatisBatchUtils.saveOrUpdate(sqlSessionFactory, entityList, method.insert(), insertPredicate, method.updateById(), batchSize);
     }
 

+ 62 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/MapperProxyMetadata.java

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011-2025, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baomidou.mybatisplus.core.metadata;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.session.SqlSession;
+
+/**
+ * Mapper代理属性
+ *
+ * @author nieqiurong
+ * @see com.baomidou.mybatisplus.core.override.MybatisMapperProxy
+ * @see org.apache.ibatis.binding.MapperProxy
+ * @since 3.5.12
+ */
+@SuppressWarnings("LombokGetterMayBeUsed")
+public class MapperProxyMetadata {
+
+    private final SqlSession sqlSession;
+
+    private final Class<?> mapperInterface;
+
+    public MapperProxyMetadata(MetaObject metaObject) {
+        if (!metaObject.hasGetter("mapperInterface") || !metaObject.hasGetter("sqlSession")) {
+            throw new MybatisPlusException("Unable to retrieve the mapperInterface and sqlSession properties from " + metaObject.getOriginalObject());
+        }
+        this.mapperInterface = (Class<?>) metaObject.getValue("mapperInterface");
+        this.sqlSession = (SqlSession) metaObject.getValue("sqlSession");
+    }
+
+    public Class<?> getMapperInterface() {
+        return mapperInterface;
+    }
+
+    public SqlSession getSqlSession() {
+        return sqlSession;
+    }
+
+    @Override
+    public String toString() {
+        return "MapperProxy{" +
+            "mapperInterface=" + mapperInterface +
+            ", sqlSession=" + sqlSession +
+            '}';
+    }
+
+
+}

+ 3 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/override/MybatisMapperProxy.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.core.override;
 
+import com.baomidou.mybatisplus.core.metadata.MapperProxyMetadata;
 import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
@@ -171,8 +172,8 @@ public class MybatisMapperProxy<T> implements InvocationHandler, Serializable {
                 return methodHandle.bindTo(proxy).invokeWithArguments(args);
             } else {
                 try {
-                    MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(proxy);
-                    Class<?> mapperInterface = mybatisMapperProxy.getMapperInterface();
+                    MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(proxy);
+                    Class<?> mapperInterface = mapperProxyMetadata.getMapperInterface();
                     IgnoreStrategy ignoreStrategy = InterceptorIgnoreHelper.findIgnoreStrategy(mapperInterface, method);
                     if (ignoreStrategy == null) {
                         ignoreStrategy = IgnoreStrategy.builder().build();

+ 68 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java

@@ -1,8 +1,24 @@
+/*
+ * Copyright (c) 2011-2025, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.baomidou.mybatisplus.core.toolkit;
 
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
+import com.baomidou.mybatisplus.core.metadata.MapperProxyMetadata;
 import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
 import lombok.experimental.UtilityClass;
 import lombok.extern.slf4j.Slf4j;
@@ -74,12 +90,23 @@ public class MybatisUtils {
      */
     public static SqlSessionFactory getSqlSessionFactory(MybatisMapperProxy<?> mybatisMapperProxy) {
         SqlSession sqlSession = mybatisMapperProxy.getSqlSession();
+        return getSqlSessionFactory(sqlSession);
+    }
+
+    /**
+     * 获取sqlSession中的SqlSessionFactory
+     *
+     * @param sqlSession sqlSession会话
+     * @return SqlSessionFactory
+     * @since 3.5.12
+     */
+    public static SqlSessionFactory getSqlSessionFactory(SqlSession sqlSession) {
         MetaObject metaObject = SystemMetaObject.forObject(sqlSession);
         String property = "sqlSessionFactory";
         if (metaObject.hasGetter(property)) {
             return (SqlSessionFactory) metaObject.getValue(property);
         }
-        SqlSessionFactory sqlSessionFactory = GlobalConfigUtils.getGlobalConfig(mybatisMapperProxy.getSqlSession().getConfiguration()).getSqlSessionFactory();
+        SqlSessionFactory sqlSessionFactory = GlobalConfigUtils.getGlobalConfig(sqlSession.getConfiguration()).getSqlSessionFactory();
         Assert.isTrue(sqlSessionFactory != null, "Please implement access to the sqlSessionFactory property or bind sqlSessionFactory to global access.");
         return sqlSessionFactory;
     }
@@ -113,4 +140,44 @@ public class MybatisUtils {
         throw new MybatisPlusException("Unable to get MybatisMapperProxy : " + mapper);
     }
 
+    /**
+     * 提取MapperProxy
+     *
+     * @param mapper Mapper对象
+     * @return 真实Mapper对象(去除动态代理增强)
+     * @since 3.5.12
+     */
+    public static Object extractMapperProxy(Object mapper) {
+        if (mapper instanceof MybatisMapperProxy) {
+            // fast return
+            return mapper;
+        }
+        Object result = mapper;
+        if (AopUtils.isLoadSpringAop()) {
+            while (org.springframework.aop.support.AopUtils.isAopProxy(result)) {
+                result = AopProxyUtils.getSingletonTarget(result);
+            }
+        }
+        if (result != null) {
+            while (Proxy.isProxyClass(result.getClass())) {
+                result = Proxy.getInvocationHandler(result);
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * 获取MapperProxy元数据信息
+     *
+     * @param mapper Mapper对象
+     * @return 代理属性
+     * @since 3.5.12
+     */
+    public static MapperProxyMetadata getMapperProxy(Object mapper) {
+        Object mapperProxy = extractMapperProxy(mapper);
+        MetaObject metaObject = SystemMetaObject.forObject(mapperProxy);
+        return new MapperProxyMetadata(metaObject);
+    }
+
 }

+ 4 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtilsTest.java

@@ -32,6 +32,7 @@ public class MybatisUtilsTest {
         var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
         SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
         Assertions.assertNotNull(sqlSessionFactory);
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(sqlSession));
     }
 
     @Test
@@ -40,6 +41,7 @@ public class MybatisUtilsTest {
         var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
         SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
         Assertions.assertNotNull(sqlSessionFactory);
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(sqlSession));
     }
 
     @Test
@@ -47,6 +49,7 @@ public class MybatisUtilsTest {
         var sqlSession = new SqlSessionTemplate(getDefaultSqlSessionFactory());
         var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
         Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(mybatisMapperProxy));
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(sqlSession));
     }
 
     static class MySqlSessionTemplate extends SqlSessionTemplate {
@@ -61,6 +64,7 @@ public class MybatisUtilsTest {
         var sqlSession = new MySqlSessionTemplate(getDefaultSqlSessionFactory());
         var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
         Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(mybatisMapperProxy));
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(sqlSession));
     }
 
     private SqlSessionFactory getDefaultSqlSessionFactory() {

+ 5 - 5
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/AbstractRepository.java

@@ -2,7 +2,7 @@ package com.baomidou.mybatisplus.extension.repository;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
+import com.baomidou.mybatisplus.core.metadata.MapperProxyMetadata;
 import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
 import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
@@ -44,8 +44,8 @@ public abstract class AbstractRepository<M extends BaseMapper<T>, T>  implements
 
     protected SqlSessionFactory getSqlSessionFactory() {
         if (this.sqlSessionFactory == null) {
-            MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper());
-            this.sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+            MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this.getBaseMapper());
+            this.sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mapperProxyMetadata.getSqlSession());
         }
         return this.sqlSessionFactory;
     }
@@ -56,8 +56,8 @@ public abstract class AbstractRepository<M extends BaseMapper<T>, T>  implements
      */
     public Class<M> getMapperClass() {
         if (this.mapperClass == null) {
-            MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper());
-            this.mapperClass = (Class<M>) mybatisMapperProxy.getMapperInterface();
+            MapperProxyMetadata mapperProxyMetadata = MybatisUtils.getMapperProxy(this.getBaseMapper());
+            this.mapperClass = (Class<M>) mapperProxyMetadata.getMapperInterface();
         }
         return this.mapperClass;
     }