Сеттер не делегирован перехватчику ByteBuddy - PullRequest
0 голосов
/ 26 июня 2019

ОБНОВЛЕНИЕ : перехватчик действительно вызывается.Однако, если я устанавливаю точку останова в методе перехвата, точка останова не срабатывает (хотя метод действительно вызывается).Если я устанавливаю точку останова в методе, вызываемом из перехватчика, то он срабатывает (потому что точка останова не была вызвана в первом случае, это заставило меня думать, что перехватчик не был вызван)

Iя пытаюсь использовать 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
        }
    }
}

Прокси создан правильно, однако всякий раз, когда я пытаюсь вызвать сеттер для прокси-класса, EntityChangesInterceptor.intercept никогда не вызывается.

Если я изменю реализацию прокси-класса так, чтобы он перехватывал получатели следующим образом, то все работаетштраф:

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 Ответ

1 голос
/ 26 июня 2019

Создание isValueObject private делает свое дело.

...