了解切入点并访问通知中的注释参数

Understanding the pointcut and accessing the annotation parameter in advice

有人可以帮我理解 aspectj 中的以下切入点吗?

这个切入点适用于注释 @DynamicValue 但它的工作方式令人困惑。

下面是我的自定义注释:

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DynamicValue {
String lookupName() default "";
}

我的 class 使用注释:

com.package.sample;
Class SampleA{

@DynamicValue("Hello")
public String greet;

//getters & setters

}

包含切入点的方面:

@Aspect
@Configurable
@Component
public class DynamicValueAspect
{

@Pointcut("get(@com.sample.aspect.DynamicValue java.lang.String com.package.sample..*.*)")
public void isDynamicValue() {}

@Around("isDynamicValue()")
public void getLocalized(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("Annotation called");
//How can I access the parameter in annotation here 
//i.e "Hello" from the @DynamicValue("Hello")
}

切入点是否正确,在我使用 @DynamicValue 注释的任何地方它都能工作吗?

另外我想知道如何访问建议中的注释参数?

按如下方式更改您的方法签名:

@Around("isDynamicValue()")
public void getLocalized(ProceedingJoinPoint pjp, DynamicValue dynamicValue) throws Throwable {
    System.out.println(dynamic.lookupName());
}

我不太明白你是否也有切入点的问题。这是一个应该可以工作的例子

@Around("execution(@com.package.sample.DynamicValue * *(..)) && @annotation(dynamicValue)")
public void isDynamicValue() {}

译注:

package de.scrum_master.app;

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

@Target({ ElementType.FIELD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DynamicValue {
    String lookupName() default "";
}

带注释成员的驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    @DynamicValue(lookupName = "foobar")
    public String greet;
    public String anotherMember;

    public static void main(String[] args) {
        Application application = new Application();
        application.greet = "world";
        application.anotherMember = "Another member";
        application.sayHello();
    }

    private void sayHello() {
        System.out.println(anotherMember);
        System.out.println("Hello " + greet);
    }
}

看点:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;

import de.scrum_master.app.DynamicValue;

@Aspect
@Configurable
@Component
public class DynamicValueAspect {
    @Pointcut("get(String de.scrum_master.app..*) && @annotation(dynamicValue)")
    public void isDynamicValue(DynamicValue dynamicValue) {}

    @Around("isDynamicValue(dynamicValue)")
    public Object getLocalized(DynamicValue dynamicValue, ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println(thisJoinPoint);
        System.out.println("    " + dynamicValue);
        return thisJoinPoint.proceed();
    }
}

控制台日志:

Another member
get(String de.scrum_master.app.Application.greet)
    @de.scrum_master.app.DynamicValue(lookupName=foobar)
Hello world

顺便说一下,如果您不想更改 get() 的结果,@Before 建议就足够了。只是打印一些东西 @Around 是矫枉过正。


因为 OP 询问是否可以将切入点匹配限制为某种原始类型,如 int,同时捕获真实原始类型和盒装类型 Integer,我将展示一个变体只是。正如我之前所说,如果不需要操作由字段访问器切入点编辑的值 return,则也不需要使用 @Around。我们只使用 @AfterReturning 因为它有一个可选的 returning 参数,通过它我们可以将实际的 return 值绑定到建议参数。如果我们为该建议参数选择 Object 以外的其他东西 - 在这种情况下我们只使用 int - 我们得到了所要求的。

所以让我们在原始代码中添加两个类型为 intInteger 的注释参数:

带注释成员的驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    @DynamicValue(lookupName = "foobar")
    public String greet;
    public String anotherMember;
    @DynamicValue(lookupName = "primitive")
    public int primitiveNumber;
    @DynamicValue(lookupName = "boxed")
    public Integer boxedNumber;

    public static void main(String[] args) {
        Application application = new Application();
        application.greet = "world";
        application.anotherMember = "Another member";
        application.primitiveNumber = 11;
        application.boxedNumber = 22;
        application.sayHello();
    }

    private void sayHello() {
        System.out.println(anotherMember);
        System.out.println("Hello " + greet);
        System.out.println(primitiveNumber);
        System.out.println(boxedNumber);
    }
}

修改方面定位 int/Integer 仅限字段访问器:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;

import de.scrum_master.app.DynamicValue;

@Aspect
@Configurable
@Component
public class DynamicValueAspect {
    @Pointcut("get(* de.scrum_master.app..*) && @annotation(dynamicValue)")
    public void isDynamicValue(DynamicValue dynamicValue) {}

    @AfterReturning(pointcut = "isDynamicValue(dynamicValue)", returning = "field")
    public void getLocalized(DynamicValue dynamicValue, int field, JoinPoint thisJoinPoint) throws Throwable {
        System.out.println(thisJoinPoint);
        System.out.println("    " + dynamicValue);
    }
}

新控制台日志:

Another member
Hello world
get(int de.scrum_master.app.Application.primitiveNumber)
    @de.scrum_master.app.DynamicValue(lookupName=primitive)
11
get(Integer de.scrum_master.app.Application.boxedNumber)
    @de.scrum_master.app.DynamicValue(lookupName=boxed)
22

顺便说一句,我回答了一个类似的问题