理解切入点并访问建议中的注释参数

时间:2016-12-03 13:29:37

标签: java spring annotations aspectj spring-aop

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

此切入点适用于注释Set WBook = Workbooks.Open("TestData.xlsm") ,但它的工作方式令人困惑。

以下是我的自定义注释:

@DynamicValue

我的班级使用注释:

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

包含切入点的方面:

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") } 注释的任何地方使用?

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

2 个答案:

答案 0 :(得分:2)

<强>注释:

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

顺便说一下,如果您不想更改@Before的结果,get()建议就足够了。仅仅打印@Around的内容有点过分。

因为OP询问是否可以将切入点匹配限制为某个原始类型,如int,捕获真实基元和盒装类型Integer,我将展示一个变体。正如我之前所说,如果不需要操作字段访问器切入点返回的值,则也不需要使用@Around。我们只使用@AfterReturning因为它有一个可选的returning参数,通过它我们可以将实际的返回值绑定到一个advice参数。如果那时我们为该建议参数选择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字段访问者的Mofified方面:

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
顺便说一下,我回答了类似的问题here

答案 1 :(得分:0)

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

@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() {}