簡體   English   中英

無法使用 bytebuddy 更改參數值

[英]Failing to change the argument value using bytebuddy

我正在嘗試使用 bytebuddy 添加查詢參數以請求 url 這是我的代碼:

new AgentBuilder.Default()
    .disableClassFormatChanges()
    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
    .type(hasSuperType(named("org.springframework.web.client.RestTemplate")))
    .transform(new Transformer.ForAdvice().include(MyByteBuddy.class.getClassLoader())
    .advice(ElementMatchers.named("execute"), "agent.RestTemplateAdvice"))
    .installOn(instrumentation);

和建議是

@Advice.OnMethodEnter
public static void before(@Advice.AllArguments Object[] args) {
    System.out.println("!!!!!!!!!!!");
    String data = args[0].toString();
    data = (data + "asdgb?param=myparam");
    System.out.println(data);
    args[0] = (Object)data;
    System.out.println(args[0]);
}

output 我得到的是

!!!!!!!!!!!
http://localhost:8086/movies/5678asdgb?param=myparam
http://localhost:8086/movies/5678

我也嘗試過以下建議,但這個建議甚至沒有捕獲方法調用。

@Advice.OnMethodEnter
public static void before(@Advice.Argument(0) String argument) {
    System.out.println("!!!!!!!!!!!");
    argument = (argument + "asdgb?param=myparam");
    System.out.println(argument);
}

就像你說的,為了改變你需要的論點readOnly = false 但正如我所說,您的建議並未涵蓋所有三種execute()方法。 對於將URI作為第一個參數的異常,您將獲得 class 強制轉換異常。 以下是修復方法:

使您的示例代碼編譯的幫助程序類:

public class MyByteBuddy {}
import org.springframework.web.client.RestTemplate;

public class MyRestTemplate extends RestTemplate {}

字節好友建議:

import net.bytebuddy.asm.Advice;

import java.net.URI;
import java.net.URISyntaxException;

import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;

public class RestTemplateAdvice {
  @Advice.OnMethodEnter()
  public static void before(
    @Advice.Argument(value = 0, typing = DYNAMIC, readOnly = false) Object url
  )
    throws URISyntaxException
  {
    String newURL = url.toString() + "search?q=scrum";
    url = url instanceof URI ? new URI(newURL) : newURL;
    System.out.println(url);
  }
}

司機申請:

import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import org.springframework.web.client.HttpClientErrorException;

import java.lang.instrument.Instrumentation;
import java.net.URI;
import java.net.URISyntaxException;

import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.springframework.http.HttpMethod.GET;

class BBChangeRestTemplateReturnValue_64257928 {
  public static void main(String[] args) throws URISyntaxException {
    applyAdvice();
    performSampleRequests();
  }

  private static void applyAdvice() {
    Instrumentation instrumentation = ByteBuddyAgent.install();
    new AgentBuilder.Default()
      .disableClassFormatChanges()
      .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
      .type(hasSuperType(named("org.springframework.web.client.RestTemplate")))
      .transform(
        new AgentBuilder.Transformer.ForAdvice()
          .include(MyByteBuddy.class.getClassLoader())
          .advice(named("execute"), "RestTemplateAdvice")
      )
      .installOn(instrumentation);
  }

  private static void performSampleRequests() throws URISyntaxException {
    try {
      new MyRestTemplate().execute("https://www.google.com/", GET, null, null);
    }
    catch (HttpClientErrorException ignored) {}
    try {
      new MyRestTemplate().execute(new URI("https://www.google.com/"), GET, null, null);
    }
    catch (HttpClientErrorException ignored) {}
  }
}

控制台日志:

https://www.google.com/search?q=scrum
https://www.google.com/search?q=scrum

使用@AllArguments時的問題是您正在分配一個值

args[0] = (Object) data;

這對 Byte Buddy 的模板功能沒有幫助。 實際上,這意味着您正在將所有 arguments 讀入一個數組,將data分配給該數組的第一個索引,然后不再使用它。 相反,您需要:

Object[] _args = args;
_args[0] = (Object) data;
args = _args;

雖然這在 Java 代碼中似乎沒有意義,但它轉換為您想要的字節代碼,其中所有 arguments 都分配了提供的數組的值。 然而,按照kriegaex建議對 arguments 使用索引基礎代理會更有效。

暫無
暫無

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

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