例如,假设有一个接口(StoredOnDatabase)带有一些有用的方法,可以从数据库中读取和写入bean。假设有一些类没有实现这个接口,而是用注释@bean进行了注释。当这个注释出现时,我想:
我不想改变POJO的类别。一个简单的解决方案可以是在实例化bean之前使用ByteBuddy完成所有这些。这可能是一个解决方案,但我想知道是否可以将bean实例化为一个干净的POJO并添加代理的其他功能。
我正在尝试使用ByteBuddy,我认为我有一个可行的解决方案,但它似乎比我预想的要复杂得多。
如上所述,我需要代理类的实例,以便向它们添加新的接口,拦截对现有方法的调用,并替换现有方法(主要是equals()、hashCode()和toString())。
似乎与我所需要的比较接近的示例是以下内容(复制自ByteBuddy教程):
class Source {
public String hello(String name) { return null; }
}
class Target {
public static String hello(String name) {
return "Hello " + name + "!";
}
}
String helloWorld = new ByteBuddy()
.subclass(Source.class)
.method(named("hello")).intercept(MethodDelegation.to(Target.class))
.make()
.load(getClass().getClassLoader())
.getLoaded()
.newInstance()
.hello("World");
我是不是漏掉了什么?
这里有一个AspectJ解决方案。我认为这比ByteBuddy版本简单得多,可读性更强。让我们从与前面相同的resource
类开始:
package de.scrum_master.app;
public class Resource {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
现在,让我们通过AspectJ的ITD(inter-type definition)将以下内容添加到resource
类中。导言:
id
成员的构造函数ToString()
方法等于(*)
方法package de.scrum_master.aspect;
import de.scrum_master.app.Resource;
public aspect MethodIntroductionAspect {
public Resource.new(String id) {
this();
setId(id);
}
public boolean Resource.equals(Object obj) {
if (!(obj instanceof Resource))
return false;
return getId().equals(((Resource) obj).getId());
}
public String Resource.toString() {
return "Resource[id=" + getId() + "]";
}
}
package de.scrum_master.app;
import static org.junit.Assert.*;
import org.junit.Test;
public class ResourceTest {
@Test
public void useConstructorWithArgument() {
assertNotEquals(null, new Resource("dummy"));
}
@Test
public void testToString() {
assertEquals("Resource[id=dummy]", new Resource("dummy").toString());
}
@Test
public void testEquals() {
assertEquals(new Resource("A"), new Resource("A"));
assertNotEquals(new Resource("A"), new Resource("B"));
}
}
Marco,也许我不能让你相信这比你自己的解决方案更好,但是如果我可以并且你需要一个Maven POM,请告诉我。
更新:
我刚刚为您创建了简单的Maven POM(单模块项目):
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>aspectj-itd-example-57525767</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.source-target.version>8</java.source-target.version>
<aspectj.version>1.9.4</aspectj.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<!-- IMPORTANT -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<!--<showWeaveInfo>true</showWeaveInfo>-->
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${java.source-target.version}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<!--<verbose>true</verbose>-->
<!--<warn>constructorName,packageDefaultMethod,deprecation,maskedCatchBlocks,unusedLocals,unusedArguments,unusedImport</warn>-->
</configuration>
<executions>
<execution>
<!-- IMPORTANT -->
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
其次,出于测试目的,我停用了IntelliJ IDEA Ultimate中的AspectJ和Spring AOP插件,出于所有的意图和目的,在这里将我的IDE变成了关于AspectJ的社区版。当然,对于AspectJ、本机语法或方面交叉引用信息,您没有特定的语法高亮显示(在应用程序代码中编织了哪些建议或方面代码在哪里编织?)但对ITD的支持是有限的。例如,在单元测试中,您似乎会看到编译问题,因为IDE不知道ITS的构造函数和方法。
但如果现在打开设置对话并将IDE构建委托给Maven...
...您可以从IntelliJ IDEA构建,通过用户界面等运行单元测试。在右边当然您有Maven视图,也可以运行Maven目标。顺便说一句,如果IDEA询问您是否要启用Maven自动导入,您应该接受。
我还将相同的Maven POM导入到一个新的Eclipse项目(安装了AJDT)中,它也运行良好。IDEA和Eclipse项目在一个项目目录中和平共处。
附注:在IDEA Ultimate中,委托给Maven也是必要的,以避免IDE中的编译错误,因为AspectJ ITD支持在IDEA中是如此糟糕。
我正在用bytebuddyapi编写一个Java代理。因此,我想了解使用Bytebuddy DSL的重传功能加载的类的方法委派。当我使用参数javaagent启动应用程序时,一切正常,控制台输出也会更改,但当在运行时附加java代理时,会执行agentmain方法,但控制台输出不会更改。也许我错过了一些进一步的ByteBuddy配置。任何帮助都将不胜感激! 这是代理代码: 以下是应用程序代码: 这
我需要从Spring应用程序向MongoDB实例抛出文档,在那里我可以利用其数据包中的MongoTemplate。 但是Spring将那些instances字段作为MongoDB文档id,导致数据库中的id重复,从而防止了重复的实例。 null 通过阅读这个问题,我发现字段对于Spring是必需的,我需要添加一个字段。 这就是我将文档插入集合的方式: 我对ByteBuddy完全陌生(我认为这可能是
我正在尝试在项目中检测一些类。当我将代理类打包到jar中并通过-javaagent使用它时,它工作正常。 当我尝试直接在项目中运行它时,检测有时会失败。(我在测试类的静态块中初始化bytepal)。 例如,当我添加这个测试时,我的代码不再被截获。用try/catch做同样的事情是有效的。 有没有一种安全的方法来仪器类在同一个项目没有-javaagent? 项目在OpenJdk11上。
我需要使用远程代理服务器进行测试,但代理需要登录名和密码进行授权。我尝试使用: 帮助我理解我的错误,我确定这是可能的,但如何。我有一个例外:
线程“main”java.lang.LinkageError:loader(sun/misc/launcher$AppClassLoader的实例):试图重复名称:“TestClass”的类定义 我正在尝试实现代理,如:easly-create-java-agents-with-bytebuddy中描述的示例所示 是否有一种方法可以加载Class对象而不导致此问题,或者使用传递给transform
问题内容: 如果我这样做 它打印 问题是,我在代理后面。JVM在Windows的哪里获取代理信息?我该如何设置?我所有其他应用似乎都对我的代理感到非常满意。 问题答案: 从Java 1.5开始,你还可以将实例传递给该方法: 如果你的代理服务器要求身份验证,它将给你响应407。 在这种情况下,你需要以下代码: