簡體   English   中英

如何將ByteBuddy @Pipe批注與@FieldValue一起使用以實現委托模式?

[英]How to use ByteBuddy @Pipe annotation with @FieldValue to implement delegate pattern?

使用ByteBuddy,我試圖找到一種有效的方式來生成代理,該代理將所有方法調用簡單地轉發到相同類型的基礎委托實例,而我遇到了這一問題: 如何在Java中實現包裝裝飾器? ,我嘗試實施建議的解決方案,但沒有取得任何成功,表面上我的粗略猜測是在不了解ByteBuddy的內部知識的情況下,當檢查以下內容時,似乎可以考慮將以下intercept方法的@FieldValue注釋參數考慮在內匹配委托的方法簽名? 我的用例稍微復雜一點,但是我寫了一個簡單的單元測試來重現同樣的問題,我使用的是ByteBuddy版本1.5.13:

@Test
public void testDelegate() throws Exception {

    Object delegate = "aaa";

    Class<?> delegateClass = new ByteBuddy().subclass(Object.class)
            .method(ElementMatchers.any()).intercept(MethodDelegation.to(Interceptor.class).defineParameterBinder(Pipe.Binder.install(Function.class)))
            .defineField("delegate", Object.class, Modifier.PUBLIC)
            .make()
            .load(getClass().getClassLoader())
            .getLoaded();

    Object obj = delegateClass.newInstance();
    delegateClass.getField("delegate").set(obj, delegate);

    assertThat(obj, equalTo("aaa"));
}

該攔截器工作正常,並且單元測試成功通過:

public static class Interceptor {

    @RuntimeType
    public static Object intercept(@Pipe Function<Object, Object> pipe) {
        return pipe.apply("aaa");
    }
}

但是,如果我用上面的這個替換上面的Interceptor,並嘗試使用@FieldValue注入委托字段:

public static class Interceptor {

    @RuntimeType
    public static Object intercept(@Pipe Function<Object, Object> pipe, @FieldValue("delegate") Object delegate) {
        return pipe.apply(delegate);
    }
}

我收到以下錯誤:

java.lang.IllegalArgumentException: None of [public static java.lang.Object io.github.pellse.decorator.DecoratorTest$Interceptor.intercept(java.util.function.Function,java.lang.Object)] allows for delegation from public boolean java.lang.Object.equals(java.lang.Object)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.process(MethodDelegationBinder.java:881)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1278)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:678)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:667)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:586)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:4305)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1796)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:172)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:153)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2568)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2670)
at io.github.pellse.decorator.DecoratorTest.testDelegate(DecoratorTest.java:476)

所以我想知道我是否正確使用了@ Pipe / @ FieldValue批注,或者在生成帶有ByteBuddy的代理時是否還有另一種方法來委托方法調用? 提前致謝!

使用appendParameterBinder而不是defineParameterBinder解決了此問題, TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTSMethodDelegation.to(TypeDescription typeDescription)MethodDelegation.to(TypeDescription typeDescription)指定的默認TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTS ,因此不再定義@FieldValue ,這是我的錯誤。 每天我都在使用ByteBuddy,該庫的質量給我越來越深刻的印象!

對於轉發,我實際上建議您使用MethodCall.invokeSelf().onField(delegate) ,該方法的性能要比應用更復雜的匹配的MethodDelegation更好。 請注意,委托可以與諸如MethodDelegation.to( ... ).andThen(MethodCall.invokeSelf().onField(delegate)

另外,我剛剛在即將發布的v1.6中更改了委托API,以避免您遇到的混亂並允許進行多項性能改進。

重要提示 :如果受保護的方法是由不同於檢測類型的另一個包中的類型定義的,則無法通過管道傳遞這些方法。 當前版本的Byte Buddy錯過了此檢查,但從1.6.1開始,它將引發異常。 您可以通過not(isProtected())排除此類方法。 Object::clonejava.定義的這種方法的典型候選Object::clone java. 包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM