簡體   English   中英

如何使用Byte Buddy創建默認構造函數

[英]How to create a default constructor with Byte Buddy

我想攔截我的一個類上的一些方法調用,但這些類沒有默認的構造函數。

鑒於以下類,我如何設置Byte Buddy也創建一個公共無參數構造函數來創建生成的類?

public class GetLoggedInUsersSaga extends AbstractSpaceSingleEventSaga {
    private final UserSessionRepository userSessionRepository;

    @Inject
    public GetLoggedInUsersSaga(final UserSessionRepository userSessionRepository) {
        this.userSessionRepository = userSessionRepository;
    }

    @StartsSaga
    public void handle(final GetLoggedInUsersRequest request) {
       // this is the method in want to intercept
    }
}

編輯:具體的用例是簡化單元測試設置。
目前我們總是要寫這樣的東西:

@Test
public void someTest() {
   // Given

   // When
   GetLoggedInUsersRequest request = new GetLoggedInUsersRequest();
   setMessageForContext(request); // <-- always do this before calling handle
   sut.handle(request);

   // Then
}

我認為在@Before方法中創建代理會自動為您設置上下文會很好。

@Before
public void before()  {
    sut = new GetLoggedInUsersSaga(someDependency);
    sut = intercept(sut);
}

@Test
public void someTest() {
   // Given

   // When
   GetLoggedInUsersRequest request = new GetLoggedInUsersRequest();
   sut.handle(request);

   // Then
}

我玩了一下但不幸的是我沒有讓它工作..

public <SAGA extends Saga> SAGA intercept(final SAGA sagaUnderTest) throws NoSuchMethodException, IllegalAccessException, InstantiationException {
    return (SAGA) new ByteBuddy()
            .subclass(sagaUnderTest.getClass())
            .defineConstructor(Collections.<Class<?>>emptyList(), Visibility.PUBLIC)
            .intercept(MethodCall.invokeSuper())
            .method(ElementMatchers.isAnnotatedWith(StartsSaga.class))
            .intercept(
                    MethodDelegation.to(
                            new Object() {
                                @RuntimeType
                                public Object intercept(
                                        @SuperCall Callable<?> c,
                                        @Origin Method m,
                                        @AllArguments Object[] a) throws Exception {
                                    setMessageForContext((Message) a[0]);
                                    return c.call();
                                }
                            }))
            .make()
            .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded()
            .newInstance();
}

不幸的是現在我得到了(可能是因為ctor調用仍未正確設置)

java.lang.IllegalStateException: Cannot invoke public com.frequentis.ps.account.service.audit.GetLoggedInUsersSaga$ByteBuddy$zSZuwhtR() as a super method

這甚至是正確的方法嗎?
我應該在這里使用字節伙伴還是更容易/其他方式?

您無法定義沒有任何字節代碼的構造函數。 這將是一個抽象的構造函數,在Java中是非法的。 我將為javadoc添加更精確的描述,以用於將來的版本。 謝謝你引起我的注意。

您需要定義任何構造函數所需的超級方法調用:

DynamicType.Builder builder = ...
builder = builder
  .defineConstructor(Collections.<Class<?>>emptyList(), Visibility.PUBLIC)
  .intercept(MethodCall
               .invoke(superClass.getDeclaredConstructor())
               .onSuper())

至於你應該在這里使用Byte Buddy:我不能用我看到的小代碼告訴你。 您應該問的問題是:它是否使我的代碼更容易,既考慮了代碼量又遵循了代碼的復雜性? 如果Byte Buddy使您的代碼更易於使用(並運行),請使用它。 如果沒有,請不要使用它。

暫無
暫無

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

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