Browse Source

解决AOP增强Mapper层导致的错误.

https://github.com/baomidou/mybatis-plus/issues/5741
nieqiurong 1 year ago
parent
commit
08cf31f415

+ 1 - 1
build.gradle

@@ -38,7 +38,7 @@ ext {
         "spring-tx"                  : "org.springframework:spring-tx:${springVersion}",
         "spring-web"                 : "org.springframework:spring-web:${springVersion}",
         "spring-aop"                 : "org.springframework:spring-aop:${springVersion}",
-        "aspectjrt"                  : "org.aspectj:aspectjrt:1.9.20.1",
+        "aspectjweaver"                  : "org.aspectj:aspectjweaver:1.9.20.1",
         "cglib"                      : "cglib:cglib:3.3.0",
         "imadcn"                     : "com.imadcn.framework:idworker:1.5.0",
         "spring-cloud-commons"       : "org.springframework.cloud:spring-cloud-commons:${springCloudVersion}",

+ 1 - 1
mybatis-plus-extension/build.gradle

@@ -24,6 +24,6 @@ dependencies {
     implementation "com.github.ben-manes.caffeine:caffeine:2.9.3"
     testImplementation "com.github.pagehelper:pagehelper:5.3.1"
     testImplementation "com.google.guava:guava:31.1-jre"
-    testImplementation "io.github.classgraph:classgraph:+"
+    testImplementation "io.github.classgraph:classgraph:4.8.163"
     testImplementation "${lib.h2}"
 }

+ 25 - 4
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java

@@ -33,6 +33,8 @@ import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.mybatis.spring.SqlSessionTemplate;
 import org.mybatis.spring.SqlSessionUtils;
+import org.springframework.aop.framework.AopProxyUtils;
+import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.core.convert.support.DefaultConversionService;
@@ -57,6 +59,17 @@ import java.util.function.Function;
 @SuppressWarnings("unchecked")
 public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
 
+    private static boolean loadAop = false;
+
+    static {
+        try {
+            ClassUtils.toClassConfident("org.springframework.aop.framework.AopProxyUtils");
+            loadAop = true;
+        } catch (Exception exception) {
+            // ignore
+        }
+    }
+
     private final ConversionService conversionService = DefaultConversionService.getSharedInstance();
 
     protected final Log log = LogFactory.getLog(getClass());
@@ -82,14 +95,22 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
 
     private volatile SqlSessionFactory sqlSessionFactory;
 
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings({"rawtypes", "deprecation"})
     protected SqlSessionFactory getSqlSessionFactory() {
         if (this.sqlSessionFactory == null) {
             synchronized (this) {
                 if (this.sqlSessionFactory == null) {
-                    MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(this.baseMapper);
-                    SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
-                    this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
+                    Object target = this.baseMapper;
+                    if (loadAop && AopUtils.isAopProxy(this.baseMapper)) {
+                        target = AopProxyUtils.getSingletonTarget(this.baseMapper);
+                    }
+                    if (target != null) {
+                        MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(target);
+                        SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
+                        this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
+                    } else {
+                        this.sqlSessionFactory = GlobalConfigUtils.currentSessionFactory(this.entityClass);
+                    }
                 }
             }
         }

+ 2 - 1
mybatis-plus/build.gradle

@@ -12,7 +12,8 @@ dependencies {
     testImplementation "${lib.'javax.servlet-api'}"
 
     testImplementation "${lib.'spring-test'}"
-
+    testImplementation "${lib.'spring-aop'}"
+    testImplementation "${lib.'aspectjweaver'}"
     testImplementation "${lib."jackson"}"
     testImplementation "${lib."fastjson"}"
     testImplementation "${lib."gson"}"

+ 34 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig1.java

@@ -0,0 +1,34 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * @author nieqiurong
+ */
+@Aspect
+@EnableAspectJAutoProxy
+public class AopConfig1 {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig1.class);
+
+    @Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
+    public void point() {
+    }
+
+    @Before("point()")
+    public void before() {
+        LOGGER.info("before ...");
+    }
+
+    @After("point()")
+    public void after() {
+        LOGGER.info("After ...");
+    }
+
+}

+ 26 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig2.java

@@ -0,0 +1,26 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author nieqiurong
+ */
+@Aspect
+public class AopConfig2 {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig2.class);
+
+    @Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
+    public void point() {
+    }
+
+    @Before("point()")
+    public void before() {
+        LOGGER.info("before ...");
+    }
+
+}

+ 41 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AppConfig.java

@@ -0,0 +1,41 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.h2.Driver;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+
+import javax.sql.DataSource;
+
+/**
+ * @author nieqiurong
+ */
+@Configuration
+@ComponentScan("com.baomidou.mybatisplus.test.h2.issues.aop")
+@MapperScan("com.baomidou.mybatisplus.test.h2.issues.aop.mapper")
+public class AppConfig {
+
+    @Bean
+    public DataSource dataSource() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/MultiAopTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class, AopConfig2.class})
+public class MultiAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 45 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/NoAopTest.java

@@ -0,0 +1,45 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class})
+public class NoAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/SingleAopTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class, AopConfig1.class})
+public class SingleAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/entity/Demo.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.entity;
+
+import lombok.Data;
+
+/**
+ * @author nieqiurong
+ */
+@Data
+public class Demo {
+
+    private Long id;
+
+    private String name;
+
+}

+ 13 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/mapper/DemoMapper.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author nieqiurong
+ */
+@Mapper
+public interface DemoMapper extends BaseMapper<Demo> {
+
+}

+ 11 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/IDemoService.java

@@ -0,0 +1,11 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+
+/**
+ * @author nieqiurong
+ */
+public interface IDemoService extends IService<Demo> {
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/impl/DemoServiceImpl.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.mapper.DemoMapper;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author nieqiurong
+ */
+@Service
+public class DemoServiceImpl extends ServiceImpl<DemoMapper, Demo> implements IDemoService {
+
+}