简体   繁体   中英

Spring AOP Pointcut expression for annotated field

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.

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:

Marker annotation:

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 {}

Driver application:

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);
    }
}

Aspect:

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);
    }
}

Console log:

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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM