zhou-hao 5 лет назад
Родитель
Сommit
343e2bed9b
12 измененных файлов с 246 добавлено и 166 удалено
  1. 1 1
      hsweb-authorization/hsweb-authorization-api/custom-data-access.md
  2. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccess.java
  3. 0 23
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizingContext.java
  4. 39 62
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java
  5. 0 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DefaultDataAccessController.java
  6. 82 35
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldFilterDataAccessHandler.java
  7. 44 0
      hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java
  8. 15 3
      hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java
  9. 13 3
      hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorContext.java
  10. 49 34
      hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java
  11. 1 2
      hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java
  12. 1 1
      hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupport.java

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/custom-data-access.md

@@ -40,7 +40,7 @@ public class MyDataAccessHandler implements org.hswebframework.web.authorization
         @Override
         public boolean handle(DataAccessConfig access, MethodInterceptorParamContext context) {
             //被拦截的方法参数
-           Map<String,Object> param= context.getParams();
+           Map<String,Object> param= context.getNamedArguments();
            // 判断逻辑
            //...
             return true;

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccess.java

@@ -29,7 +29,7 @@ import java.lang.annotation.*;
  *
  * @author zhouhao
  * @see DataAccessController
- * @see Authorize#dataAccess()
+ * @see ResourceAction#dataAccess()
  * @since 3.0
  */
 @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD})

+ 0 - 23
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizingContext.java

@@ -21,27 +21,4 @@ public class AuthorizingContext {
 
     private MethodInterceptorContext paramContext;
 
-    public AuthorizeDefinition getDefinition() {
-        return definition;
-    }
-
-    public void setDefinition(AuthorizeDefinition definition) {
-        this.definition = definition;
-    }
-
-    public Authentication getAuthentication() {
-        return authentication;
-    }
-
-    public void setAuthentication(Authentication authentication) {
-        this.authentication = authentication;
-    }
-
-    public MethodInterceptorContext getParamContext() {
-        return paramContext;
-    }
-
-    public void setParamContext(MethodInterceptorContext paramContext) {
-        this.paramContext = paramContext;
-    }
 }

+ 39 - 62
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java

@@ -1,5 +1,6 @@
 package org.hswebframework.web.authorization.basic.aop;
 
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
@@ -11,10 +12,12 @@ import org.hswebframework.web.authorization.basic.handler.AuthorizingHandler;
 import org.hswebframework.web.authorization.define.*;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.utils.AnnotationUtils;
+import org.reactivestreams.Publisher;
 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RestController;
 import reactor.core.publisher.Flux;
@@ -22,6 +25,10 @@ import reactor.core.publisher.Mono;
 
 import java.lang.reflect.Method;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 /**
@@ -51,81 +58,48 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
         this.autoParse = autoParse;
     }
 
-    protected Mono<?> handleReactive(AuthorizeDefinition definition, MethodInterceptorHolder holder, AuthorizingContext context, Mono<?> mono) {
 
-        return Authentication.currentReactive()
-                .switchIfEmpty(Mono.error(new UnAuthorizedException()))
-                .flatMap(auth -> {
-                    ResourcesDefinition resources = definition.getResources();
-
-                    context.setAuthentication(auth);
-                    if (definition.getPhased() == Phased.before) {
-                        authorizingHandler.handRBAC(context);
-                        if (resources != null && resources.getPhased() == Phased.before) {
-                            authorizingHandler.handleDataAccess(context);
-                        } else {
-                            return mono.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handleDataAccess(context);
-                            });
-                        }
-                    } else {
-                        if (resources != null && resources.getPhased() == Phased.before) {
-                            authorizingHandler.handleDataAccess(context);
-                            return mono.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handRBAC(context);
-                            });
-                        } else {
-                            return mono.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handle(context);
-                            });
-                        }
-
-                    }
-                    return mono;
-                });
-    }
-
-    protected Flux<?> handleReactive(AuthorizeDefinition definition, MethodInterceptorHolder holder, AuthorizingContext context, Flux<?> flux) {
+    protected Publisher<?> handleReactive0(AuthorizeDefinition definition,
+                                           MethodInterceptorHolder holder,
+                                           AuthorizingContext context,
+                                           Supplier<? extends Publisher<?>> invoker) {
 
         return Authentication.currentReactive()
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .flatMapMany(auth -> {
-                    ResourcesDefinition resources = definition.getResources();
-
                     context.setAuthentication(auth);
-                    if (definition.getPhased() == Phased.before) {
+                    Function<Runnable, Publisher> afterRuner = runnable -> {
+                        MethodInterceptorContext interceptorContext = holder.createParamContext(invoker.get());
+                        runnable.run();
+                        return (Publisher<?>) interceptorContext.getInvokeResult();
+                    };
+                    if (context.getDefinition().getPhased() != Phased.after) {
                         authorizingHandler.handRBAC(context);
-                        if (resources != null && resources.getPhased() == Phased.before) {
+                        if (context.getDefinition().getResources().getPhased() != Phased.after) {
                             authorizingHandler.handleDataAccess(context);
+                            return invoker.get();
                         } else {
-                            return flux.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handleDataAccess(context);
-                            });
+                            return afterRuner.apply(() -> authorizingHandler.handleDataAccess(context));
                         }
-                    } else {
 
-                        if (resources != null && resources.getPhased() == Phased.before) {
+                    } else {
+                        if (context.getDefinition().getResources().getPhased() != Phased.after) {
                             authorizingHandler.handleDataAccess(context);
-                            return flux.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handRBAC(context);
-                            });
+                            return invoker.get();
                         } else {
-                            return flux.doOnNext(res -> {
-                                context.setParamContext(holder.createParamContext(res));
-                                authorizingHandler.handle(context);
+                            return afterRuner.apply(() -> {
+                                authorizingHandler.handRBAC(context);
+                                authorizingHandler.handleDataAccess(context);
                             });
                         }
-
                     }
-                    return flux;
                 });
     }
 
+    @SneakyThrows
+    private <T> T doProceed(MethodInvocation invocation) {
+        return (T) invocation.proceed();
+    }
 
     @Override
     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
@@ -136,17 +110,20 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
         AuthorizeDefinition definition = aopMethodAuthorizeDefinitionParser.parse(methodInvocation.getThis().getClass(), methodInvocation.getMethod(), paramContext);
         Object result = null;
         boolean isControl = false;
-        if (null != definition) {
+        if (null != definition && !definition.isEmpty()) {
             AuthorizingContext context = new AuthorizingContext();
             context.setDefinition(definition);
             context.setParamContext(paramContext);
 
             Class<?> returnType = methodInvocation.getMethod().getReturnType();
             //handle reactive method
-            if (Mono.class.isAssignableFrom(returnType)) {
-                return handleReactive(definition, holder, context, ((Mono<?>) methodInvocation.proceed()));
-            } else if (Flux.class.isAssignableFrom(returnType)) {
-                return handleReactive(definition, holder, context, ((Flux<?>) methodInvocation.proceed()));
+            if (Publisher.class.isAssignableFrom(returnType)) {
+                Publisher publisher = handleReactive0(definition, holder, context, () -> doProceed(methodInvocation));
+                if (Mono.class.isAssignableFrom(returnType)) {
+                    return Mono.from(publisher);
+                } else if (Flux.class.isAssignableFrom(returnType)) {
+                    return Flux.from(publisher);
+                }
             }
 
             Authentication authentication = Authentication.current().orElseThrow(UnAuthorizedException::new);
@@ -224,7 +201,7 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
             log.info("publish AuthorizeDefinitionInitializedEvent,definition size:{}", definitions.size());
             eventPublisher.publishEvent(new AuthorizeDefinitionInitializedEvent(definitions));
 
-          //  defaultParser.destroy();
+            //  defaultParser.destroy();
         }
     }
 

+ 0 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DefaultDataAccessController.java

@@ -30,7 +30,6 @@ public final class DefaultDataAccessController implements DataAccessController {
             throw new UnsupportedOperationException();
         }
         this.parent = parent;
-
                 addHandler(new FieldFilterDataAccessHandler());
     }
 

+ 82 - 35
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldFilterDataAccessHandler.java

@@ -8,10 +8,13 @@ import org.hswebframework.web.authorization.access.DataAccessHandler;
 import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
 import org.hswebframework.web.authorization.define.AuthorizingContext;
 import org.hswebframework.web.authorization.define.Phased;
+import org.reactivestreams.Publisher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
 import java.util.Collection;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -46,6 +49,22 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
         }
     }
 
+    protected void applyUpdateParam(FieldFilterDataAccessConfig config, Object... parameter) {
+
+        for (Object data : parameter) {
+            for (String field : config.getFields()) {
+                try {
+                    //设置值为null,跳过修改
+                    BeanUtilsBean.getInstance()
+                            .getPropertyUtils()
+                            .setProperty(data, field, null);
+                } catch (Exception e) {
+                    logger.warn("can't set {} null", field, e);
+                }
+            }
+        }
+    }
+
     /**
      * @param accesses 不可操作的字段
      * @param params   参数上下文
@@ -54,52 +73,80 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
      * @see org.apache.commons.beanutils.PropertyUtilsBean
      */
     protected boolean doUpdateAccess(FieldFilterDataAccessConfig accesses, AuthorizingContext params) {
-        Map<String, Object> paramsMap = params.getParamContext().getParams();
-
-        Object supportParam = paramsMap.size() == 1 ?
-                paramsMap.values().iterator().next() :
-                paramsMap.values().stream()
-                       // .filter(param -> (param instanceof Entity) || (param instanceof Model) || (param instanceof Map))
-                        .findAny()
-                        .orElse(null);
-        if (null != supportParam) {
-            for (String field : accesses.getFields()) {
-                try {
-                    //设置值为null,跳过修改
-                    BeanUtilsBean.getInstance()
-                            .getPropertyUtils()
-                            .setProperty(supportParam, field, null);
-                } catch (Exception e) {
-                    logger.warn("can't set {} null", field, e);
-                }
+
+        boolean reactive = params.getParamContext().handleReactiveArguments(publisher -> {
+            if (publisher instanceof Mono) {
+                return Mono.from(publisher)
+                        .doOnNext(data -> applyUpdateParam(accesses, data));
+
             }
-        } else {
-            logger.warn("doUpdateAccess skip ,because can not found any support entity in param!");
+            if (publisher instanceof Flux) {
+                return Flux.from(publisher)
+                        .doOnNext(data -> applyUpdateParam(accesses, data));
+
+            }
+            return publisher;
+        });
+        if (reactive) {
+            return true;
         }
+
+        applyUpdateParam(accesses, params.getParamContext().getArguments());
         return true;
     }
 
+    @SuppressWarnings("all")
+    protected void applyQueryParam(FieldFilterDataAccessConfig config, Object param) {
+        if (param instanceof QueryParam) {
+            Set<String> denyFields = config.getFields();
+            ((QueryParam) param).excludes(denyFields.toArray(new String[0]));
+            return;
+        }
+
+        Object r = InvokeResultUtils.convertRealResult(param);
+        if (r instanceof Collection) {
+            ((Collection) r).forEach(o -> setObjectPropertyNull(o, config.getFields()));
+        } else {
+            setObjectPropertyNull(r, config.getFields());
+        }
+
+    }
+
     @SuppressWarnings("all")
     protected boolean doQueryAccess(FieldFilterDataAccessConfig access, AuthorizingContext context) {
         if (context.getDefinition().getResources().getPhased() == Phased.before) {
-            QueryParam entity = context.getParamContext().getParams()
-                    .values().stream()
-                    .filter(QueryParam.class::isInstance)
-                    .map(QueryParam.class::cast)
-                    .findAny().orElse(null);
-            if (entity == null) {
-                logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
+
+            boolean reactive = context
+                    .getParamContext()
+                    .handleReactiveArguments(publisher -> {
+                        if (publisher instanceof Mono) {
+                            return Mono.from(publisher)
+                                    .doOnNext(param -> {
+                                        applyQueryParam(access, param);
+                                    });
+                        }
+                        return publisher;
+                    });
+
+            if (reactive) {
                 return true;
             }
-            Set<String> denyFields = access.getFields();
-            entity.excludes(denyFields.toArray(new String[denyFields.size()]));
+
+            for (Object argument : context.getParamContext().getArguments()) {
+                applyQueryParam(access, argument);
+            }
         } else {
-            Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
-            if (result instanceof Collection) {
-                ((Collection) result).forEach(o -> setObjectPropertyNull(o, access.getFields()));
-            } else {
-                setObjectPropertyNull(result, access.getFields());
+            if (context.getParamContext().getInvokeResult() instanceof Publisher) {
+                context.getParamContext().setInvokeResult(
+                        Flux.from((Publisher<?>) context.getParamContext().getInvokeResult())
+                                .doOnNext(result -> {
+                                    applyQueryParam(access, result);
+                                })
+                );
+
+                return true;
             }
+            applyQueryParam(access, context.getParamContext().getInvokeResult());
         }
         return true;
     }

+ 44 - 0
hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java

@@ -1,13 +1,17 @@
 package org.hswebframework.web.authorization.basic.aop;
 
+import org.hswebframework.ezorm.core.param.Param;
+import org.hswebframework.ezorm.core.param.QueryParam;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.ReactiveAuthenticationHolder;
 import org.hswebframework.web.authorization.ReactiveAuthenticationSupplier;
 import org.hswebframework.web.authorization.User;
+import org.hswebframework.web.authorization.basic.handler.access.FieldFilterDataAccessHandler;
 import org.hswebframework.web.authorization.basic.web.ReactiveUserTokenParser;
 import org.hswebframework.web.authorization.exception.AccessDenyException;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.simple.SimpleAuthentication;
+import org.hswebframework.web.authorization.simple.SimpleFieldFilterDataAccessConfig;
 import org.hswebframework.web.authorization.simple.SimplePermission;
 import org.hswebframework.web.authorization.simple.SimpleUser;
 import org.hswebframework.web.authorization.token.ParsedToken;
@@ -25,6 +29,7 @@ import reactor.test.StepVerifier;
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 
 import static org.junit.Assert.*;
 
@@ -69,4 +74,43 @@ public class AopAuthorizingControllerTest {
                 .expectNext("403")
                 .verifyComplete();
     }
+
+    @Test
+    public void testFiledDeny(){
+        SimpleAuthentication authentication = new SimpleAuthentication();
+
+        SimpleFieldFilterDataAccessConfig config=new SimpleFieldFilterDataAccessConfig();
+        config.setAction("query");
+        config.setFields(new HashSet<>(Arrays.asList("name")));
+
+        authentication.setUser(SimpleUser.builder().id("test").username("test").build());
+        authentication.setPermissions(Arrays.asList(SimplePermission.builder()
+                .actions(Collections.singleton("query"))
+                .dataAccesses(Collections.singleton(config))
+                .id("test").build()));
+
+        ReactiveAuthenticationHolder.addSupplier(new ReactiveAuthenticationSupplier() {
+            @Override
+            public Mono<Authentication> get(String userId) {
+                return Mono.empty();
+            }
+
+            @Override
+            public Mono<Authentication> get() {
+                return Mono.just(authentication);
+            }
+        });
+
+        testController.queryUser(new QueryParam())
+                .map(Param::getExcludes)
+                .as(StepVerifier::create)
+                .expectNextMatches(f->f.contains("name"))
+                .verifyComplete();
+
+        testController.queryUser(Mono.just(new QueryParam()))
+                .map(Param::getExcludes)
+                .as(StepVerifier::create)
+                .expectNextMatches(f->f.contains("name"))
+                .verifyComplete();
+    }
 }

+ 15 - 3
hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java

@@ -1,10 +1,10 @@
 package org.hswebframework.web.authorization.basic.aop;
 
+import org.hswebframework.ezorm.core.param.QueryParam;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.User;
-import org.hswebframework.web.authorization.annotation.Authorize;
-import org.hswebframework.web.authorization.annotation.QueryAction;
-import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.annotation.*;
 import org.hswebframework.web.authorization.define.Phased;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.springframework.web.bind.annotation.RestController;
@@ -27,4 +27,16 @@ public class TestController {
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .map(Authentication::getUser);
     }
+
+    @QueryAction(dataAccess = @DataAccess(type = @DataAccessType(id= DataAccessConfig.DefaultType.DENY_FIELDS,name = "禁止访问字段")))
+    public Mono<QueryParam> queryUser(QueryParam queryParam) {
+        return Mono.just(queryParam);
+    }
+
+    @QueryAction(dataAccess = @DataAccess(type = @DataAccessType(id= DataAccessConfig.DefaultType.DENY_FIELDS,name = "禁止访问字段")))
+    public Mono<QueryParam> queryUser(Mono<QueryParam> queryParam) {
+        return queryParam;
+    }
+
+
 }

+ 13 - 3
hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorContext.java

@@ -18,11 +18,14 @@
 
 package org.hswebframework.web.aop;
 
+import org.reactivestreams.Publisher;
+
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.Function;
 
 /**
  * AOP拦截到方法的参数上下文,用于获取当前进行操作的方法的各种参数信息,如:当前所在类实例,参数集合,注解
@@ -55,7 +58,7 @@ public interface MethodInterceptorContext extends Serializable {
      * @param <T>  参数泛型
      * @return Optional
      */
-    <T> Optional<T> getParameter(String name);
+    <T> Optional<T> getArgument(String name);
 
     /**
      * 获取当前操作方法或实例上指定类型的泛型,如果方法上未获取到,则获取实例类上的注解。实例类上未获取到,则返回null
@@ -70,9 +73,16 @@ public interface MethodInterceptorContext extends Serializable {
      * 获取全部参数
      *
      * @return 参数集合
-     * @see this#getParameter(String)
+     * @see this#getArgument(String)
      */
-    Map<String, Object> getParams();
+    Map<String, Object> getNamedArguments();
+
+    Object[] getArguments();
+
+    boolean handleReactiveArguments(Function<Publisher<?>, Publisher<?>> handler);
 
     Object getInvokeResult();
+
+    void setInvokeResult(Object result);
+
 }

+ 49 - 34
hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java

@@ -18,22 +18,29 @@
 
 package org.hswebframework.web.aop;
 
+import lombok.AllArgsConstructor;
+import lombok.Getter;
 import org.aopalliance.intercept.MethodInvocation;
 import org.hswebframework.web.utils.AnnotationUtils;
+import org.reactivestreams.Publisher;
 import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
 import org.springframework.core.ParameterNameDiscoverer;
 import org.springframework.util.DigestUtils;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Function;
 
 /**
  * @author zhouhao
  */
+@AllArgsConstructor
+@Getter
 public class MethodInterceptorHolder {
     /**
      * 参数名称获取器,用于获取方法参数的名称
@@ -48,9 +55,12 @@ public class MethodInterceptorHolder {
         for (int i = 0, len = args.length; i < len; i++) {
             argMap.put((argNames == null || argNames[i] == null) ? "arg" + i : argNames[i], args[i]);
         }
+
         return new MethodInterceptorHolder(id,
                 invocation.getMethod(),
-                invocation.getThis(), argMap);
+                invocation.getThis(),
+                args,
+                argMap);
     }
 
     private String id;
@@ -59,34 +69,10 @@ public class MethodInterceptorHolder {
 
     private Object target;
 
-    private Map<String, Object> args;
-
-    public MethodInterceptorHolder(String id, Method method, Object target, Map<String, Object> args) {
-        Objects.requireNonNull(id);
-        Objects.requireNonNull(method);
-        Objects.requireNonNull(target);
-        Objects.requireNonNull(args);
-        this.id = id;
-        this.method = method;
-        this.target = target;
-        this.args = args;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public Method getMethod() {
-        return method;
-    }
+    private Object[] arguments;
 
-    public Object getTarget() {
-        return target;
-    }
+    private Map<String, Object> namedArguments;
 
-    public Map<String, Object> getArgs() {
-        return args;
-    }
 
     public <T extends Annotation> T findMethodAnnotation(Class<T> annClass) {
         return AnnotationUtils.findMethodAnnotation(annClass, method, annClass);
@@ -107,6 +93,30 @@ public class MethodInterceptorHolder {
     public MethodInterceptorContext createParamContext(Object invokeResult) {
         return new MethodInterceptorContext() {
             private static final long serialVersionUID = -4102787561601219273L;
+            private Object result = invokeResult;
+
+            @Override
+            public Object[] getArguments() {
+                return arguments;
+            }
+
+            public boolean handleReactiveArguments(Function<Publisher<?>, Publisher<?>> handler) {
+                boolean handled = false;
+                Object[] args = getArguments();
+                if (args == null || args.length == 0) {
+                    return false;
+                }
+                for (int i = 0; i < args.length; i++) {
+                    Object arg = args[i];
+                    if (arg instanceof Publisher) {
+                        args[i] = handler.apply(((Mono) arg));
+                        handled = true;
+                    }
+                }
+
+                return handled;
+            }
+
 
             @Override
             public Object getTarget() {
@@ -119,11 +129,11 @@ public class MethodInterceptorHolder {
             }
 
             @Override
-            public <T> Optional<T> getParameter(String name) {
-                if (args == null) {
+            public <T> Optional<T> getArgument(String name) {
+                if (namedArguments == null) {
                     return Optional.empty();
                 }
-                return Optional.ofNullable((T) args.get(name));
+                return Optional.ofNullable((T) namedArguments.get(name));
             }
 
             @Override
@@ -132,13 +142,18 @@ public class MethodInterceptorHolder {
             }
 
             @Override
-            public Map<String, Object> getParams() {
-                return getArgs();
+            public Map<String, Object> getNamedArguments() {
+                return MethodInterceptorHolder.this.getNamedArguments();
             }
 
             @Override
             public Object getInvokeResult() {
-                return invokeResult;
+                return result;
+            }
+
+            @Override
+            public void setInvokeResult(Object result) {
+                this.result = result;
             }
         };
     }

+ 1 - 2
hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java

@@ -22,7 +22,6 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
-import java.util.function.Function;
 
 import static org.hswebframework.web.datasource.strategy.AnnotationDataSourceSwitchStrategyMatcher.*;
 
@@ -112,7 +111,7 @@ public class AopDataSourceSwitcherAutoConfiguration {
                                     String id = strategy.getDataSourceId();
                                     if (StringUtils.hasText(id)) {
                                         if (id.contains("${")) {
-                                            id = ExpressionUtils.analytical(id, context.getParams(), "spel");
+                                            id = ExpressionUtils.analytical(id, context.getNamedArguments(), "spel");
                                         }
                                         if (!DataSourceHolder.existing(id)) {
                                             if (strategy.isFallbackDefault()) {

+ 1 - 1
hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupport.java

@@ -90,7 +90,7 @@ public class AopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor {
             info.setAction(define.getAction());
             info.setDescribe(define.getDescribe());
         }
-        info.setParameters(holder.getArgs());
+        info.setParameters(holder.getNamedArguments());
         info.setTarget(holder.getTarget().getClass());
         info.setMethod(holder.getMethod());