From 6979a0833ec220f7d34c6c2768bde1b8b78505b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Sun, 27 Jul 2025 16:19:43 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E6=8A=8A=E6=95=B0=E6=8D=AE=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=B3=A8=E8=A7=A3=E5=85=A8=E9=83=A8=E4=BA=A4=E7=BB=99?= =?UTF-8?q?AOP=E5=A4=84=E7=90=86=EF=BC=8C=E4=BD=BF=E7=94=A8=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=8A=A8=E6=80=81=E6=96=B9=E6=B3=95=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=99=A8=E5=8C=B9=E9=85=8D=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/aop/DataPermissionAdvice.java | 54 +++++++++++++++++++ .../DataPermissionDynamicMethodMatcher.java | 46 ++++++++++++++++ .../aop/DataPermissionPointcutAdvisor.java | 38 +++++++++++++ .../mybatis/aspect/DataPermissionAspect.java | 50 ----------------- .../mybatis/config/MybatisPlusConfig.java | 11 ++-- 5 files changed, 146 insertions(+), 53 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionAdvice.java create mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionDynamicMethodMatcher.java create mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionPointcutAdvisor.java delete mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionAdvice.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionAdvice.java new file mode 100644 index 000000000..468b1d5b5 --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionAdvice.java @@ -0,0 +1,54 @@ +package org.dromara.common.mybatis.aop; + +import lombok.extern.slf4j.Slf4j; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.helper.DataPermissionHelper; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * 数据权限注解Advice + * + * @author 秋辞未寒 + */ +@Slf4j +public class DataPermissionAdvice implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object target = invocation.getThis(); + Method method = invocation.getMethod(); + Object[] args = invocation.getArguments(); + // 设置权限注解 + DataPermissionHelper.setPermission(getDataPermissionAnnotation(target, method, args)); + try { + // 执行代理方法 + return invocation.proceed(); + } finally { + // 清除权限注解 + DataPermissionHelper.removePermission(); + } + } + + /** + * 获取数据权限注解 + */ + private DataPermission getDataPermissionAnnotation(Object target, Method method,Object[] args){ + DataPermission dataPermission = method.getAnnotation(DataPermission.class); + // 优先获取方法上的注解 + if (dataPermission != null) { + return dataPermission; + } + // 方法上没有注解,则获取类上的注解 + Class targetClass = target.getClass(); + // 如果是 JDK 动态代理,则获取真实的Class实例 + if (Proxy.isProxyClass(targetClass)) { + targetClass = targetClass.getInterfaces()[0]; + } + dataPermission = targetClass.getAnnotation(DataPermission.class); + return dataPermission; + } +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionDynamicMethodMatcher.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionDynamicMethodMatcher.java new file mode 100644 index 000000000..76905607d --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionDynamicMethodMatcher.java @@ -0,0 +1,46 @@ +package org.dromara.common.mybatis.aop; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.springframework.aop.support.DynamicMethodMatcher; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * 数据权限动态方法匹配器 + * + * @author 秋辞未寒 + */ +@Slf4j +@SuppressWarnings("all") +public class DataPermissionDynamicMethodMatcher extends DynamicMethodMatcher { + + public DataPermissionDynamicMethodMatcher() {} + + @Override + public boolean matches(Method method, Class targetClass) { + // 优先匹配方法 + // 数据权限注解不对继承生效,所以检查当前方法是否有注解即可,不再往上匹配父类或接口 + if (method.isAnnotationPresent(DataPermission.class)) { + return true; + } + + // TODO MyBatis 的 Mapper 就是通过 JDK 动态代理实现的,所以这里需要检查是否匹配 JDK 的动态代理 + Class targetClassRef = targetClass; + if (Proxy.isProxyClass(targetClassRef)) { + // 数据权限注解不对继承生效,但由于 SpringIOC 容器拿到的实际上是 MyBatis 代理过后的 Mapper,而 targetClass.isAnnotationPresent 实际匹配的是 Proxy 类的注解,不会查找代理类。 + // 所以这里不能用 targetClass.isAnnotationPresent,只能用 AnnotatedElementUtils.hasAnnotation 或 targetClass.getInterfaces()[0].isAnnotationPresent 去做匹配,以检查被代理的 MapperClass 是否具有注解 + // 原理:JDK 动态代理本质上就是对接口进行实现然后对具体的接口实现做代理,所以直接通过接口可以拿到实际的 MapperClass + targetClassRef = targetClass.getInterfaces()[0]; + + } + return targetClassRef.isAnnotationPresent(DataPermission.class); + } + + @Override + public boolean matches(Method method, Class targetClass, Object... args) { + return matches(method, targetClass); + } + +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionPointcutAdvisor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionPointcutAdvisor.java new file mode 100644 index 000000000..17cc90bef --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aop/DataPermissionPointcutAdvisor.java @@ -0,0 +1,38 @@ +package org.dromara.common.mybatis.aop; + +import org.aopalliance.aop.Advice; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.AbstractPointcutAdvisor; +import org.springframework.aop.support.ComposablePointcut; +import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; + +/** + * 数据权限注解切面定义 + * + * @author 秋辞未寒 + */ +@SuppressWarnings("all") +public class DataPermissionPointcutAdvisor extends AbstractPointcutAdvisor { + + private final Advice advice; + private final Pointcut pointcut; + + public DataPermissionPointcutAdvisor() { + this.advice = new DataPermissionAdvice(); + AnnotationMatchingPointcut matchingPointcut = new AnnotationMatchingPointcut(DataPermission.class, true); + DataPermissionDynamicMethodMatcher matcher = new DataPermissionDynamicMethodMatcher(); + this.pointcut = new ComposablePointcut(matcher).union(matchingPointcut); + } + + @Override + public Pointcut getPointcut() { + return this.pointcut; + } + + @Override + public Advice getAdvice() { + return this.advice; + } + +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java deleted file mode 100644 index 1c83cc392..000000000 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.dromara.common.mybatis.aspect; - -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.AfterThrowing; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.dromara.common.mybatis.annotation.DataPermission; -import org.dromara.common.mybatis.helper.DataPermissionHelper; - -/** - * 数据权限处理 - * - * @author Lion Li - */ -@Slf4j -@Aspect -public class DataPermissionAspect { - - /** - * 处理请求前执行 - */ - @Before(value = "@annotation(dataPermission)") - public void doBefore(JoinPoint joinPoint, DataPermission dataPermission) { - DataPermissionHelper.setPermission(dataPermission); - } - - /** - * 处理完请求后执行 - * - * @param joinPoint 切点 - */ - @AfterReturning(pointcut = "@annotation(dataPermission)") - public void doAfterReturning(JoinPoint joinPoint, DataPermission dataPermission) { - DataPermissionHelper.removePermission(); - } - - /** - * 拦截异常操作 - * - * @param joinPoint 切点 - * @param e 异常 - */ - @AfterThrowing(value = "@annotation(dataPermission)", throwing = "e") - public void doAfterThrowing(JoinPoint joinPoint, DataPermission dataPermission, Exception e) { - DataPermissionHelper.removePermission(); - } - -} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index 00c26912e..7d410217c 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -11,15 +11,18 @@ import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerIntercept import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.dromara.common.core.factory.YmlPropertySourceFactory; import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.mybatis.aspect.DataPermissionAspect; +import org.dromara.common.mybatis.aop.DataPermissionPointcutAdvisor; import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler; import org.dromara.common.mybatis.handler.MybatisExceptionHandler; import org.dromara.common.mybatis.handler.PlusPostInitTableInfoHandler; import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Role; import org.springframework.transaction.annotation.EnableTransactionManagement; /** @@ -61,8 +64,10 @@ public class MybatisPlusConfig { * 数据权限切面处理器 */ @Bean - public DataPermissionAspect dataPermissionAspect() { - return new DataPermissionAspect(); + @ConditionalOnMissingBean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + public DataPermissionPointcutAdvisor dataPermissionPointcutAdvisor() { + return new DataPermissionPointcutAdvisor(); } /**