Spring AOP Pointcut expression for annotated field

☆樱花仙子☆ 提交于 2019-12-23 03:43:07

问题


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.


回答1:


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]


来源:https://stackoverflow.com/questions/39493383/spring-aop-pointcut-expression-for-annotated-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!