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

3

有没有可能捕获具有特定注释的任何字段?我的最终目标是将一个值注入到该字段中,但是目前我的切入点是错误的(不确定正确的语法)。

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

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

我认为这个切入点声明了任何带有注释的方法,我想将其更改为声明任何字段。


2
“capture any field” 是什么意思?Spring(基于代理的)AOP 仅适用于拦截方法调用。 - Sotirios Delimanolis
很好的观点。那么,也许我的方法应该是将切入点放在该字段的setter方法上? - Tony Card
你提到了 _inject_。为什么不使用内置的自动装配机制呢? - Sotirios Delimanolis
我可以。我只是试图用更具体和自定义的注释来掩盖特定字段的注入。 - Tony Card
考虑使用 BeanPostProcessor 替代。 - Sotirios Delimanolis
与此相关的编程内容:http://codereview.stackexchange.com/q/140938/117089 - Tony Card
1个回答

4
我认为你应该遵循Sotirios Delimanolis的建议,尽可能地使用Spring。如果你仍然认为它们不足够并且一定要使用aspect来实现你的想法,那么你可以使用Spring中的AspectJ而不是Spring AOP,并利用切入点的全部功能,如get()set()来拦截类成员(静态和非静态)的读/写操作。例如: 标记注释:
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字段。

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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接