设置器未委托给ByteBuddy拦截器

时间:2019-06-25 21:33:57

标签: byte-buddy

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();

1 个答案:

答案 0 :(得分:1)

将isValueObject设为私有可以解决问题。