2

我正在使用 AspectJ 为带有 @BindableClass 标记的任何类编织自定义 PropertyChangeSupport 引擎。它查找带有@BindableMethod 标记的方法并拦截“set”调用以触发一系列propertyChangeListener。一切正常,但我只想拦截其值为 @BindableMethod(type=Type.SET) 的方法,因为我将此注释用于 PCS 之外的功能。我在切入点的语法上有些挣扎,如果有人可以帮助我,我将不胜感激。

我可以通过在寻找字段名称时检查注释的值来破解它,但我更愿意让 aspectJ 查找为我做这件事。我认为关键在下面的“切入点”声明中。

抱歉,如果我描述得不好,我已经有几年没有和 AspectJ 一起玩了。我找到了一些关于注释查找的答案,但没有找到注释值。

我的注释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindableMethod {
    String fieldName();

    Type type() default Type.SET;

    public static enum Type {
        GET, SET;
    }
}

我的观点:

public aspect PropertySupportAspect {
/**
 * Weave any class which is tagged with @BindableClass with NestedPropertyChangeSupport
 */
declare parents: @BindableClass * implements PropertySupport, IBindable;

NestedPropertyChangeSupport PropertySupport.support = new NestedPropertyChangeSupport(this);

public interface PropertySupport {
    public void addPropertyChangeListener(PropertyChangeListener listener);

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener);

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);

    public void removePropertyChangeListener(PropertyChangeListener listener);

    public boolean hasListeners(String propertyName);

    public void firePropertyChange(Object b, String property, Object oldval, Object newval);
}

public PropertyChangeSupport PropertySupport.changeSupport() {
    return support;
}

public void PropertySupport.addPropertyChangeListener(PropertyChangeListener listener) {
    support.addPropertyChangeListener(listener);
}

public void PropertySupport.addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
    support.addPropertyChangeListener(propertyName, listener);
}

public void PropertySupport.removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
    support.removePropertyChangeListener(propertyName, listener);
}

public void PropertySupport.removePropertyChangeListener(PropertyChangeListener listener) {
    support.removePropertyChangeListener(listener);
}

public boolean PropertySupport.hasListeners(String propertyName) {
    return support.hasListeners(propertyName);
}

pointcut callSetter(PropertySupport b) : 
    call( @BindableMethod * *(..) ) 
    && target( b );

void around(PropertySupport b) : callSetter( b )  
{
    Field propertyField = getField(thisJoinPointStaticPart.getSignature());
    try {
        propertyField.setAccessible(true);
        Object oldValue = propertyField.get(b);
        proceed(b);
        Object newValue = propertyField.get(b);
        ((PropertySupport) b).firePropertyChange(b, propertyField.getName(), oldValue, newValue);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private Field getField(Signature signature) {
    Field field = null;

    try {
        MethodSignature ms = (MethodSignature) signature;
        Method m = ms.getMethod();
        BindableMethod annotation = m.getAnnotation(BindableMethod.class);
        field = signature.getDeclaringType().getDeclaredField(annotation.fieldName());
    } catch (NoSuchFieldException nsfe) {
        nsfe.printStackTrace();
    }
    return field;

}

public void PropertySupport.firePropertyChange(Object b, String property, Object oldval, Object newval) {
    support.firePropertyChange(property, oldval, newval);

}

}

我的测试班:

@BindableClass
    private class Child {
        public static final String FLD_NAME = "name";
        private String name;

        @BindableMethod(fieldName = FLD_NAME)
        public void setName(String name) {
            this.name = name;
        }

        @BindableMethod(fieldName = FLD_NAME, type = Type.GET)
        public String getName() {
            return name;
        }
    }
4

2 回答 2

1

目前这是不可能的,但在aspectj-users邮件列表上进行了讨论:

您可能想赶上讨论,看看核心开发人员何时真正有时间适当地扩展 AspectJ 语法。

于 2013-05-04T14:08:08.750 回答
1
pointcut callSetter(PropertySupport b, BindableMethod bm) : 
    call(@BindableMethod * *(..)) 
    && target(b)
    && @annotation(bm);

void around(PropertySupport b,BindableMethod bm) : callSetter( b,bm ){
    bm.type();
}
于 2016-09-25T21:59:44.497 回答