You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring自定义注解如何像@PreAuthorize一样使用配置常量?

问题分析

你遇到的核心问题是:@PreAuthorize依赖Spring的SpEL(Spring表达式语言)解析器自动处理注解中的表达式,而自定义注解默认没有内置这个解析逻辑,所以切面中拿到的只是原始字符串,而非解析后的实际值。

解决方案

要让自定义注解支持SpEL表达式解析,需要手动在切面中实现SpEL的解析逻辑,步骤如下:

1. 注入Spring上下文与SpEL解析器

在切面类中注入ApplicationContext(用于获取容器中的Bean),并初始化SpelExpressionParser(SpEL的核心解析器)。

2. 解析注解中的SpEL表达式

在切面方法中,获取注解的原始表达式,构建StandardEvaluationContext并注册Bean解析器,最终解析出实际值。

完整切面代码

@Aspect
@Component
public class AuditAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(AuditAspect.class);

    private final ApplicationContext applicationContext;
    private final ExpressionParser expressionParser = new SpelExpressionParser();

    // 构造注入ApplicationContext
    public AuditAspect(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Before("@annotation(audit)")
    public void beforeAuditedMethod(JoinPoint joinPoint, Audit audit) {
        String actionExpr = audit.action();
        // 构建SpEL评估上下文,注册Bean解析器以支持@beanName的引用
        StandardEvaluationContext evalContext = new StandardEvaluationContext();
        evalContext.setBeanResolver((beanName) -> applicationContext.getBean(beanName));

        // 解析表达式并获取实际值
        String actualAction = expressionParser.parseExpression(actionExpr).getValue(evalContext, String.class);
        LOGGER.info("audit action: {}", actualAction);
    }
}

3. 优化配置类(可选)

你当前的配置类通过静态字段同步配置值的方式可以简化,直接使用@ConfigurationProperties的绑定,无需静态字段,更符合Spring的Bean管理规范:

@Configuration("action")
@ConfigurationProperties(prefix = "action")
public class ActionProperties {
    private String create;
    private String update;
    private String delete;

    // 生成getter(Spring Boot 2.2+支持构造绑定或属性绑定,无需手动写setter)
    public String getCreate() {
        return create;
    }

    public String getUpdate() {
        return update;
    }

    public String getDelete() {
        return delete;
    }
}

此时使用注解时改为引用Bean的属性:

@Audit(action = "@action.create")
@PreAuthorize的实现原理

@PreAuthorize是Spring Security提供的注解,其底层由MethodSecurityInterceptor拦截处理:

  • 拦截器提取注解中的表达式字符串
  • 使用Spring内置的SpEL解析器解析表达式,支持@beanName引用容器中的Bean、#paramName引用方法参数、authentication引用安全上下文等变量
  • 解析完成后执行权限校验逻辑

内容的提问来源于stack exchange,提问作者user21264578

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:39:24