我正在使用 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;
}
}