Spring如何向自定义注解传递方法命名参数及自定义权限参数?
需求可实现,具体实现方案如下
Java注解本身不支持直接引用方法参数作为属性值(注解属性只能是编译期常量),我们可以通过「注解传参数名+切面动态解析参数值」的方式达成目标,该方案可通用到所有自定义注解的参数传递场景。
1. 先定义权限枚举(可选,也可直接用字符串)
public enum PermissionType { READ, WRITE }
2. 调整自定义注解定义
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AuthorizeUser { // 要获取的方法参数名列表 String[] paramNames() default {}; // 权限类型 PermissionType permission(); }
3. 完善切面逻辑
核心逻辑是通过方法签名获取参数名和参数值的映射关系,再根据注解中配置的参数名提取对应的值:
@Aspect @Component public class AuthorizeUserAspect { @Autowired PermissionService permissionService; // Spring自带的参数名解析器 private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); @Around("@annotation(authorizeUser)") public Object authorize(ProceedingJoinPoint joinPoint, AuthorizeUser authorizeUser) throws Throwable { // 1. 获取当前拦截的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 2. 获取方法的参数名数组、参数值数组 String[] paramNames = parameterNameDiscoverer.getParameterNames(method); Object[] paramValues = joinPoint.getArgs(); // 3. 构建参数名-参数值映射 Map<String, Object> paramMap = new HashMap<>(); if (paramNames != null) { for (int i = 0; i < paramNames.length; i++) { paramMap.put(paramNames[i], paramValues[i]); } } // 4. 从注解中获取配置的参数名,提取对应的值 String[] requiredParamNames = authorizeUser.paramNames(); Object jwtAuthUser = paramMap.get(requiredParamNames[0]); Object businessId = paramMap.get(requiredParamNames[1]); // 5. 获取权限参数 PermissionType permission = authorizeUser.permission(); // 此处填写自定义权限校验逻辑 // permissionService.check(jwtAuthUser, businessId, permission); return joinPoint.proceed(); } }
4. Controller层使用示例
@AuthorizeUser(paramNames = {"jwtAuthUser", "businessId"}, permission = PermissionType.READ) @GetMapping("/businesses/{businessId}/test") public ResponseEntity<List<BusinessDto>> getBusinessListAsClient(Principal jwtAuthUser, @PathVariable String businessId) throws Exception { // 业务逻辑 }
方案说明
这套实现完全脱离参数位置限制,只要注解中填写的参数名和方法签名的参数名一致就能正确取值,逻辑可直接复用到其他自定义注解场景,不需要修改核心解析代码。
内容的提问来源于stack exchange,提问作者Mankind1023
相关产品推荐
相关产品推荐

