UPDATE :确实调用了拦截器。但是,如果我在拦截方法中设置了断点,则不会触发断点(尽管确实调用了该方法)。如果我在拦截器调用的方法中设置了断点,则会触发该断点(因为在第一种情况下未触发该断点,因此我一开始就以为没有调用该拦截器)
我正在尝试使用ByteBuddy来实现一个代理类,以跟踪一个实体上的所有更改,如下所示:
public class EntityProxyGenerator{
public static <T extends Entity> T createProxy(T entity) throws NoSuchMethodException, InstantiationException, IllegalAccessException,
InvocationTargetException {
EntityChangesInterceptor interceptor = new EntityChangesInterceptor(entity);
_class = entity.getClass();
Class Proxy =
new ByteBuddy()
.subclass(_class)
.method(ElementMatchers.isSetter())
.intercept(MethodDelegation.to(interceptor))
.make()
.load(EntityProxyGenerator.class.getClassLoader())
.getLoaded();
return (T) Proxy.getDeclaredConstructor().newInstance();
}
}
EntityChangesInterceptor
的实现如下:
public class EntityChangesInterceptor<T extends Entity> {
private final T original;
public EntityChangesInterceptor(T original) {
this.original = original;
}
public boolean isValueObject(Object object) {
Class<?> class_ = object.getClass();
if (class_ == String.class
|| class_ == Integer.class
|| class_ == Double.class
|| class_ == Timestamp.class
|| class_ == Instant.class) {
return true;
}
return false;
}
boolean isPropertyGetter(Method method, Object[] args) {
return method.getName().startsWith("get") && args.length == 0;
}
boolean isPropertySetter(Method method, Object[] args) {
return method.getName().startsWith("set") && args.length == 1;
}
@RuntimeType
public Object intercept(@Origin Method method, @AllArguments Object[] args) throws Throwable {
try {
if (isPropertySetter(method, args)) {
if (isValueObject(args[0])) {
String propertyName = method.getName().substring(3);
String getter = "get" + propertyName;
Object oldValue = MethodUtils.invokeMethod(original, getter, null);
Object newValue = args[0];
ValueChange valueChange = new ValueChange(propertyName, oldValue, newValue);
Object callResult = method.invoke(original, args);
original.addPropertyChange(valueChange);
return callResult;
}
}
return method.invoke(original, args);
} finally {
// do your completion logic here
}
}
}
正确创建了代理,但是,每当我尝试在代理类上调用setter时,都不会调用EntityChangesInterceptor.intercept
。
如果我更改代理类实现,以使其按如下方式拦截getter,则一切正常:
Class Proxy = new ByteBuddy()
.subclass(_class)
.method(ElementMatchers.isGetter()) // note isGetter() instead of isSetter()
.intercept(MethodDelegation.to(interceptor))
.make()
.load(EntityProxyGenerator.class.getClassLoader())
.getLoaded();
答案 0 :(得分:1)
将isValueObject设为私有可以解决问题。