带注释字段的Spring AOP切入点表达式

带注释字段的Spring AOP切入点表达式

问题描述:

是否可以捕获带有特定注释的任何字段?我的最终目标是在该字段中注入一个值,但是目前我的切入点是错误的(不确定语法是否正确).

Is it possible to capture any field with a specific annotation? My end goal is to inject a value into that field, but currently my pointcut is wrong (not sure of the correct syntax).

@Pointcut("execution(* *(..)) && @annotation(com.mycompany.MyAnnotation)")
private void annotatedField(){}

@Around("annotatedField()")
public Object injectValue(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {}

我相信切入点说明了带有注释的任何方法.我想将其更改为任何字段.

I believe the pointcut is stating any Method with the annotation. and I want to change that to say any Field.

我认为您应该遵循 Sotirios Delimanolis 的建议,并尽量利用Spring的内置方法.如果那时您仍然认为它们不足,并且绝对希望使用方面来实现您的想法,则可以使用

I think you should follow the advice of Sotirios Delimanolis and get as far as possible with Spring on-board means. If then you still think they are inadequate and absolutely want to use aspects to implement your idea, you can use AspectJ within Spring instead of Spring AOP and utilise the full power of pointcuts like get() and set() in order to intercept read/write operations on class members (both static and non-static). For example:

标记注释:

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {}

驱动程序应用程序:

应用程序读取(toString())并写入(构造函数,主方法)所有字段,其中包括带注释的status字段.

The application reads (toString()) and writes (constructor, main method) all fields, among them the annotated status field.

package de.scrum_master.app;

public class Application {
    private int id;
    private String name;
    @MyAnnotation private String status;

    public Application(int id, String name, String status) {
        this.id = id;
        this.name = name;
        this.status = status;
    }

    @Override
    public String toString() {
        return "Application [id=" + id + ", name=" + name + ", status=" + status + "]";
    }

    public static void main(String[] args) {
        Application application = new Application(11, "AspectJ demo", "starting");
        System.out.println(application);
        application.id = 22;
        application.name = "AspectJ field access demo";
        application.status = "running";
        System.out.println(application);
        application.status = "shutting down";
        System.out.println(application);
        application.status = "stopped";
        System.out.println(application);
    }
}

方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotatedFieldAspect {
    @Before("get(* *) && @annotation(de.scrum_master.app.MyAnnotation)")
    public void interceptRead(JoinPoint thisJoinPoint) {
        System.out.println(thisJoinPoint);
    }

    @Before("set(* *) && @annotation(de.scrum_master.app.MyAnnotation) && args(newValue)")
    public void interceptWrite(JoinPoint thisJoinPoint, Object newValue) {
        System.out.println(thisJoinPoint + " -> " + newValue);
    }
}

控制台日志:

set(String de.scrum_master.app.Application.status) -> starting
get(String de.scrum_master.app.Application.status)
Application [id=11, name=AspectJ demo, status=starting]
set(String de.scrum_master.app.Application.status) -> running
get(String de.scrum_master.app.Application.status)
Application [id=22, name=AspectJ field access demo, status=running]
set(String de.scrum_master.app.Application.status) -> shutting down
get(String de.scrum_master.app.Application.status)
Application [id=22, name=AspectJ field access demo, status=shutting down]
set(String de.scrum_master.app.Application.status) -> stopped
get(String de.scrum_master.app.Application.status)
Application [id=22, name=AspectJ field access demo, status=stopped]