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是Spring Security提供的注解,其底层由MethodSecurityInterceptor拦截处理:
- 拦截器提取注解中的表达式字符串
- 使用Spring内置的SpEL解析器解析表达式,支持
@beanName引用容器中的Bean、#paramName引用方法参数、authentication引用安全上下文等变量 - 解析完成后执行权限校验逻辑
内容的提问来源于stack exchange,提问作者user21264578
相关产品推荐
相关产品推荐

