了解切入点并访问通知中的注释参数
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
- 我们得到了所要求的。
所以让我们在原始代码中添加两个类型为 int
和 Integer
的注释参数:
带注释成员的驱动程序应用程序:
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
顺便说一句,我回答了一个类似的问题。
有人可以帮我理解 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
- 我们得到了所要求的。
所以让我们在原始代码中添加两个类型为 int
和 Integer
的注释参数:
带注释成员的驱动程序应用程序:
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
顺便说一句,我回答了一个类似的问题