spring - 在自定义注释的方面传递方法参数

标签 spring annotations aspectj spring-el

我正在尝试使用类似于 org.springframework.cache.annotation.Cacheable 的东西:

自定义注解:

@Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CheckEntity {
        String message() default "Check entity msg";
        String key() default "";
    }

方面:

@Component
@Aspect
public class CheckEntityAspect {
    @Before("execution(* *.*(..)) && @annotation(checkEntity)")
    public void checkEntity(JoinPoint joinPoint, CheckEntitty checkEntity) {
        System.out.println("running entity check: " + joinPoint.getSignature().getName());
    }
}

服务:

@Service
@Transactional
public class EntityServiceImpl implements EntityService {

    @CheckEntity(key = "#id")
    public Entity getEntity(Long id) {
        return new Entity(id);
    }
}    

我的 IDE (IntelliJ) 没有发现 key = "#id" 用法有什么特别之处,而 Cacheable 的类似用法则以不同的颜色显示比纯文本。我提到 IDE 部分只是作为提示,以防万一它有帮助,看起来 IDE 提前知道这些注释,或者它只是实现了一些在我的示例中不存在的连接。

checkEntity.key 中的值是“#id”而不是预期的数字。 我尝试使用 ExpressionParser 但可能不正确。

在 checkEntity 注释中获取参数值的唯一方法是访问参数数组,这不是我想要的,因为这个注释也可以在具有多个参数的方法中使用。

有什么想法吗?

最佳答案

使用 Spring Expression 添加另一种更简单的方法。引用如下:

您的注释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckEntity {
    String message() default "Check entity msg";
    String keyPath() default "";
}

您的服务:

@Service
@Transactional
public class EntityServiceImpl implements EntityService {

    @CheckEntity(keyPath = "[0]")
    public Entity getEntity(Long id) {
        return new Entity(id);
    }

    @CheckEntity(keyPath = "[1].otherId")
    public Entity methodWithMoreThanOneArguments(String message, CustomClassForExample object) {
        return new Entity(object.otherId);
    }
}  

class CustomClassForExample {
   Long otherId;
}

你的方面:

@Component
@Aspect
public class CheckEntityAspect {

    @Before("execution(* *.*(..)) && @annotation(checkEntity)")
    public void checkEntity(JoinPoint joinPoint, CheckEntitty checkEntity) {
        Object[] args = joinPoint.getArgs();
        ExpressionParser elParser = new SpelExpressionParser();
        Expression expression = elParser.parseExpression(checkEntity.keyPath());
        Long id = (Long) expression.getValue(args);

        // Do whatever you want to do with this id 

        // This works for both the service methods provided above and can be re-used for any number of similar methods  

    }
}

PS:我添加此解决方案是因为与其他答案相比,我觉得这是一种更简单/更清晰的方法,这可能对某人有所帮助。

关于spring - 在自定义注释的方面传递方法参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33024977/

相关文章:

java - 我可以选择在 Spring Boot 中包含/排除每个环境部署的 Controller 吗?

java - Hibernate @Any 注解用法

java - 为什么 @RequestMapping 注解在 java 中接受 String 参数而在 scala 中不接受?

java.reflection ProceedingJoinPoint

java - Hibernate 不创建表 - Spring MVC

java - Spring RestTemplate 抛出 InvalidMediaTypeException

java - 方法参数aspectj在Spring Boot中不起作用

java - AspectJ - 针对 Controller 请求方法不起作用的建议

java - Aspectj(使用 spring)- 在没有传播方法的情况下仅在抛出方法上记录一次异常抛出

java - JUnit4 根据自定义 java 注释跳过测试