我让Byte Buddy作为代理运行并且它成功地拦截了我的绝大部分代码库,顺便说一句,它是相当大的代码库!虽然有一些异常值我无法检测,我在下面记录了这些异常值,希望你能知道答案!
1. CGLIB生成的类
Spring生成一些额外的类,这些类与我的类具有相同的名称,但是"$$EnhancerByCGLIB$$"附加到末尾并且这些类导致错误.我得到的错误是:
java.lang.IllegalStateException: Cannot resolve type description for com.mycompany.MySpringBean$$EnhancerByCGLIB$$ee9d3c37_2
at net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:152)
at net.bytebuddy.pool.TypePool$LazyFacade$LazyResolution$LazyTypeDescription.resolve(TypePool.java:3158)
at net.bytebuddy.pool.TypePool$LazyFacade$LazyResolution$LazyTypeDescription.getModifiers(TypePool.java:3238)
at net.bytebuddy.ByteBuddy.rebase(ByteBuddy.java:697)
Run Code Online (Sandbox Code Playgroud)
事实上,我没有兴趣检测CGLIB生成的类,因此希望排除这些.什么是最好的方法?目前,我按名称匹配,但我想知道这是否是最佳方式.
.and(not(nameContains("EnhancerByCGLIB")))
Run Code Online (Sandbox Code Playgroud)
2.打包私有和私有类
我看到的另一个问题是检测a package private或a private class.
Package private 代码看起来像这样:
abstract class BaseBean {
Object methodA(final String customerNumber){}
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
Caused by: java.lang.IllegalAccessException:
Class net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField cannot
access a member of class com.mycompany.BaseBean with modifiers "public static"
Run Code Online (Sandbox Code Playgroud)
Private class 代码看起来像这样:
public class Object A {
//variables & methods...
private class ObjectB {}
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
Caused by: …Run Code Online (Sandbox Code Playgroud) 我有一个界面,可以说它看起来像这样。
public interface TestObject {
String getString();
Long getLong();
}
Run Code Online (Sandbox Code Playgroud)
我想使用 ByteBuddy 实际构建此对象的具体实现。
这是我尝试过的。
public class Runme {
public static void main(String[] args) {
ByteBuddy bb = new ByteBuddy();
Class<?> clz = bb
.subclass(TestObject.class)
.method(any()).intercept(MethodDelegation.to(Interceptor.class))
.make()
.load(Object.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
try {
Object test = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public class Interceptor {
public Object intercept(@Origin String method, @AllArguments Object[] args) throws Throwable {
System.out.println("I have intercepted a call");
return …Run Code Online (Sandbox Code Playgroud) 如何使用Byte Buddy添加具有给定值的注释?
我正在为JUnit生成测试类,我想通过注释生成的类@RunWith(SomeRunner.class).
为 Java 代理和检测库的代码创建单元测试的标准方法是什么?我已经使用 Byte Buddy 框架创建了一个 Java 代理,用于在 Web 应用程序之上开发分析器,现在我想为该代理编写 JUnit 测试用例。
我刚开始与ByteBuddy一起玩,并且正在研究几个示例,以便掌握它。
我试图通过此练习完成的工作是用ByteBuddy替换一些使用ASM的代码。
到目前为止,当涉及到非泛型类型时,我已经取得了成功。例如,我可以轻松地定义一个像这样的字段
builder.defineField("names", List.class, Visibility.PRIVATE)
Run Code Online (Sandbox Code Playgroud)
如果我只想创建一个原始List类型的字段。
但是,在介绍泛型时,我很困惑。
显然,我定义字段的方式(使用Class)意味着通用类型会丢失。阅读文档(尤其是该Working with generic types部分)后,我无法真正弄清楚如果List字段具有已知的通用类型(例如,如果它是另一个POJO)如何构造List字段。假设我有以下POJO:
public class Dummy {
private String name;
//getters, setters
}
Run Code Online (Sandbox Code Playgroud)
并且我想创建一个的字段List<Dummy>,我将如何完成这样的任务?
谢谢!
我正在尝试使用bytebuddy来拦截getfield和putfield访问。我已经阅读了该网站上相当全面的文档,但据我所知,它涵盖了向字段添加 getter 和 setter,而不是拦截字段访问。
这基本上是我想做的事情:
...
obj.prop = value;
x = obj.prop;
...
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我试图在字段访问之前/之后调用一些方法(或插入一些字节码)。我正在考虑使用Advice它来做到这一点,但除了方法之外,我找不到其他方法来实现它。
编辑:
我正在使用 Java 代理来执行此操作。我有一个想法,添加 adup来复制对象引用,然后调用我定义的静态方法来拦截访问(我只关心被引用的对象,而不是字段)。
最近,我使用字节伙伴开发了一个Java代理。eclipse中的开发很好,然后我将代理程序投入生产并发出以下消息:
No compatible attachment provider is available
以及从行开始的一些堆栈跟踪
static {
ByteBuddyAgent.install();
}
Run Code Online (Sandbox Code Playgroud) 受这篇文章http://mydailyjava.blogspot.com/2022/02/using-byte-buddy-for-proxy-creation.html的启发,我成功拦截了一个方法调用,检查所有方法参数的值,并返回一个模拟回应。
但是,我无法获取参数的实际名称(如源代码中所示)。我只能得到诸如“arg0”之类的名称。
我所做的最大努力是,在方法匹配器中,我可以访问方法的 MethodDescription,并且可以获得参数的 ParameterDescription。
@Override
public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) {
logger.info("OiiPlugin processing "+typeDescription);
return builder
.method(new ElementMatcher<MethodDescription>() {
@Override
public boolean matches(MethodDescription target) {
boolean isTarget = target.getDeclaredAnnotations().isAnnotationPresent(MockMe.class);
if (isTarget) {
ParameterDescription p = target.getParameters().get(0);
logger.info(
"Parameter 0 NAME:"+p.getActualName()+":"+p.getName()+":"+p.getInternalName());
};
return isTarget;
}
})
.intercept(MethodDelegation.to(
OiiInterceptor.class
));
}
Run Code Online (Sandbox Code Playgroud)
然而,它的 getActualName() 返回空字符串。
[INFO] OiiPlugin processing class com.example.research.oii.client.ExampleClient
[INFO] Parameter 0 NAME::arg0:arg0
Run Code Online (Sandbox Code Playgroud)
我确实通过 maven 插件配置添加了 javac -g:vars 参数,以指示 javac 将参数名称放入 .class 文件中。
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version> …Run Code Online (Sandbox Code Playgroud) 在撰写本文时的Byte Buddy教程中,所有内容都得到了解释,但是一个简单的after和before方法拦截器不存在,正如我在下面解释的那样,我错过了什么或者教程很复杂.(请参阅LoggerInterceptor示例给出方法但不是对象,ChangingLoggerInterceptor示例给出对象但不调用方法)
我想要实现的是在setter方法执行后调用对象的方法.如何编写拦截器并在Java 6中使用它?
public class DirtyClass{
private String _sField;
private boolean _bDirty;
public void setField(String sField) {
_sField = sField;
//setDirty(true); to be appended after proxying
}
public String getField() {
return _sField;
}
public void setDirty(boolean bDirty){
_bDirty = bDirty;
}
public boolean isDirty(){
return _bDirty;
}
}
DirtyClass d = new ByteBuddy().subclass(DirtyClass.class)...???
d.setField("dirty now");
System.out.println(d.isDirty()); //Expecting true
Run Code Online (Sandbox Code Playgroud) 我有一个简单的SpringBoot 2.1.0应用程序,并尝试使用JPA. spring-boot-starter-data-jpa一切都是通过“ ”依赖项设置的pom.xml,但是当我启动应用程序时,我得到了这个ClassNotFoundException。
我已经尝试手动添加 byte-buddy 作为依赖项,但这没有任何改变。
有人已经解决这个问题了吗?
非常感谢您提前的每一个提示!
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: net/bytebuddy/matcher/ElementMatchers
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
Caused by: java.lang.NoClassDefFoundError: net/bytebuddy/matcher/ElementMatchers
at org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl.<clinit>(BytecodeProviderImpl.java:43)
at …Run Code Online (Sandbox Code Playgroud)