> list = new ArrayList<>(SaAnnotationStrategy.instance.annotationHandlerMap.keySet());
+
+ // 额外追加的
+ if(appendHandlerList != null) {
+ for (SaAnnotationAbstractHandler> handler : appendHandlerList) {
+ Class> cls = handler.getHandlerAnnotationClass();
+ if(!list.contains(cls)) {
+ list.add(handler.getHandlerAnnotationClass());
+ }
+ }
+ }
+
+ // 计算
+ return calcClassListExpression(list);
+ }
+
+ /**
+ * 计算 class 列表的切入表达式,
+ * 最终样例形如:
+
+ public static final String POINTCUT_SIGN =
+ "@within(cn.dev33.satoken.annotation.SaCheckLogin) || @annotation(cn.dev33.satoken.annotation.SaCheckLogin) || "
+ + "@within(cn.dev33.satoken.annotation.SaCheckRole) || @annotation(cn.dev33.satoken.annotation.SaCheckRole) || "
+ + "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission)";
+
+ * @param list /
+ * @return /
+ */
+ public static String calcClassListExpression(List> list) {
+ String pointcutExpression = "";
+ for (Class> cls : list) {
+ if(!pointcutExpression.isEmpty()) {
+ pointcutExpression += " || ";
+ }
+ pointcutExpression += "@within(" + cls.getName() + ") || @annotation(" + cls.getName() + ")";
+ }
+ return pointcutExpression;
+ }
+
+
+}
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationMethodInterceptor.java b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationMethodInterceptor.java
new file mode 100644
index 00000000..44d84449
--- /dev/null
+++ b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationMethodInterceptor.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020-2099 sa-token.cc
+ *
+ * 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 cn.dev33.satoken.aop;
+
+import cn.dev33.satoken.exception.StopMatchException;
+import cn.dev33.satoken.strategy.SaAnnotationStrategy;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+
+/**
+ * Sa-Token 注解方法拦截器 AOP环绕切入
+ *
+ * @author click33
+ * @since 1.39.0
+ */
+public class SaAroundAnnotationMethodInterceptor implements MethodInterceptor {
+
+ @Override
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ // 注解鉴权
+ try{
+ Method method = invocation.getMethod();
+ SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
+ } catch (StopMatchException ignored) {
+ }
+ // 执行原有防范
+ return invocation.proceed();
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationPointcutAdvisor.java b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationPointcutAdvisor.java
new file mode 100644
index 00000000..0f108fec
--- /dev/null
+++ b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaAroundAnnotationPointcutAdvisor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2099 sa-token.cc
+ *
+ * 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 cn.dev33.satoken.aop;
+
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+
+/**
+ * Sa-Token 注解方法 Advisor AOP环绕切入
+ *
+ * @author click33
+ * @since 1.39.0
+ */
+public class SaAroundAnnotationPointcutAdvisor extends DefaultPointcutAdvisor {
+
+}
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
deleted file mode 100644
index 8d4a0e7e..00000000
--- a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2020-2099 sa-token.cc
- *
- * 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 cn.dev33.satoken.aop;
-
-import java.lang.reflect.Method;
-
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Pointcut;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import cn.dev33.satoken.strategy.SaStrategy;
-import cn.dev33.satoken.util.SaTokenConsts;
-
-/**
- * Sa-Token 基于 Spring Aop 的注解鉴权
- *
- *
- * 注意:在打开 注解鉴权 时,AOP 模式与拦截器模式不可同时使用,否则会出现在 Controller 层重复鉴权两次的问题
- *
- *
- * @author click33
- * @since 1.19.0
- */
-@Aspect
-@Component
-@Order(SaTokenConsts.ASSEMBLY_ORDER)
-public class SaCheckAspect {
-
- /**
- * 构建
- */
- public SaCheckAspect() {
- }
-
- /**
- * 定义AOP签名 (切入所有使用 Sa-Token 鉴权注解的方法)
- */
- public static final String POINTCUT_SIGN =
- "@within(cn.dev33.satoken.annotation.SaCheckLogin) || @annotation(cn.dev33.satoken.annotation.SaCheckLogin) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckRole) || @annotation(cn.dev33.satoken.annotation.SaCheckRole) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckSafe) || @annotation(cn.dev33.satoken.annotation.SaCheckSafe) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckDisable) || @annotation(cn.dev33.satoken.annotation.SaCheckDisable) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckHttpDigest) || @annotation(cn.dev33.satoken.annotation.SaCheckHttpDigest) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckOr) || @annotation(cn.dev33.satoken.annotation.SaCheckOr) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckHttpBasic) || @annotation(cn.dev33.satoken.annotation.SaCheckHttpBasic)";
-
- /**
- * 声明AOP签名
- */
- @Pointcut(POINTCUT_SIGN)
- public void pointcut() {
- }
-
- /**
- * 环绕切入
- *
- * @param joinPoint 切面对象
- * @return 底层方法执行后的返回值
- * @throws Throwable 底层方法抛出的异常
- */
- @Around("pointcut()")
- public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
-
- // 获取对应的 Method 处理函数
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Method method = signature.getMethod();
-
- // 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权
- if(SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
- // ...
- } else {
- // 注解鉴权
- SaStrategy.instance.checkMethodAnnotation.accept(method);
- }
-
- // 执行原有逻辑
- return joinPoint.proceed();
- }
-
-}
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring.factories b/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring.factories
index 9c26ddee..b4ad11e6 100644
--- a/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring.factories
+++ b/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring.factories
@@ -1 +1,2 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.aop.SaCheckAspect
\ No newline at end of file
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+cn.dev33.satoken.aop.SaAopPointcutAdvisorBeanRegister
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index 9579b4e2..ac290259 100644
--- a/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/sa-token-plugin/sa-token-spring-aop/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1 @@
-cn.dev33.satoken.aop.SaCheckAspect
\ No newline at end of file
+cn.dev33.satoken.aop.SaAopPointcutAdvisorBeanRegister
\ No newline at end of file