更改 Graphics2D 对象的文本
Change text of a Graphics2D object
我有以下代码,我想将 Graphics2D 对象 (g2D) 的文本从 "Java" 更改为新字符串,例如 "Pascal"。
import java.awt.Graphics2D;
import java.awt.font.TextLayout;
public void paint(Graphics2D g2D) {
FontRenderContext frc = g2D.getFontRenderContext();
Font font1 = new Font("Courier", Font.BOLD, 24);
String str1 = new String("Java");
TextLayout tl = new TextLayout(str1, font1, frc);
g2D.setColor(Color.gray);
tl.draw(g2D, 50, 150);
}
请注意,我无法访问方法主体(此方法是 Jar 文件的一部分,因此我无法访问方法 paint),但我可以访问方法返回的 Graphics2D 对象 (g2D)。
我打算使用 Spring AOP 并使用 @After – 运行 提取 Graphics2D 对象 (g2D),然后用新的替换文本。但是,我不知道该怎么做。在一次尝试中,在我用新文本创建一个新的 TextLayout 对象后,它在没有替换之前的文本上添加了新文本(现在我可以看到两个文本 - Java 和 Pascal)。
请告诉我如何更改添加到 Graphics2D 对象的 TextLayout 对象的文本。
如果你真的想使用 AOP 来连接到这个第 3 方 JAR,你需要使用 AspectJ,而不是 "AOP lite" 框架,例如 Spring AOP。这是因为 Spring AOP 只能拦截 Spring 组件的 public 方法执行,而不是非 Spring 的东西,例如对 JDK 方法或构造函数的调用。
拦截paint
方法@After
绘图已经完成对你也没有帮助。即使你拦截它 @Before
绘图完成了,它也不会帮助你,因为 Graphics2D
对象只是一个助手,TextLayout.draw
的一个参数。因为 TextLayout
对象,根据 API 的描述,是不可变的,你必须挂钩它的构造函数调用并修改给它的 String
参数。这是一个丑陋的 hack,但如果您在运行时为 JAR 设置编译时二进制织入或加载时织入,那么对于 AspectJ 绝对可行。
如果你能给我看更多代码或告诉我哪个 JAR 以何种方式使用,我可以更具体地回答,如果这个回复对你来说不是太技术性的话。
P.S.: 如果你描述了你真正想要达到的目标而不去想如何你认为你应该在第一时间做它也许会更好地方。也许有更简单的方法。
最后,我用Javassist解决了这个问题。因为 TextLayout 是不可变的,所以不可能更改它的值。因此,最好的解决方案(我认为)是重命名当前的 paint 方法并使用 Javassist 创建一个新方法。因此,在 运行 时间内,调用了我的新方法而不是原来的方法。代码如下:
CtClass clas = ClassPool.getDefault().get("classFullName");
CtMethod mold = clas.getMethod("MethodName", "MethodParameters");
//Rename the original method name
String nname = mname+"$impl";
mold.setName(nname);
CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
String bodyText = "New Method body";
StringBuffer body = new StringBuffer();
body.append(bodyText);
//Replace the body of the intercepter method with generated code block and add it to class.
mnew.setBody(body.toString());
clas.addMethod(mnew);
clas.writeFile();
clas.toClass();
我有以下代码,我想将 Graphics2D 对象 (g2D) 的文本从 "Java" 更改为新字符串,例如 "Pascal"。
import java.awt.Graphics2D;
import java.awt.font.TextLayout;
public void paint(Graphics2D g2D) {
FontRenderContext frc = g2D.getFontRenderContext();
Font font1 = new Font("Courier", Font.BOLD, 24);
String str1 = new String("Java");
TextLayout tl = new TextLayout(str1, font1, frc);
g2D.setColor(Color.gray);
tl.draw(g2D, 50, 150);
}
请注意,我无法访问方法主体(此方法是 Jar 文件的一部分,因此我无法访问方法 paint),但我可以访问方法返回的 Graphics2D 对象 (g2D)。
我打算使用 Spring AOP 并使用 @After – 运行 提取 Graphics2D 对象 (g2D),然后用新的替换文本。但是,我不知道该怎么做。在一次尝试中,在我用新文本创建一个新的 TextLayout 对象后,它在没有替换之前的文本上添加了新文本(现在我可以看到两个文本 - Java 和 Pascal)。
请告诉我如何更改添加到 Graphics2D 对象的 TextLayout 对象的文本。
如果你真的想使用 AOP 来连接到这个第 3 方 JAR,你需要使用 AspectJ,而不是 "AOP lite" 框架,例如 Spring AOP。这是因为 Spring AOP 只能拦截 Spring 组件的 public 方法执行,而不是非 Spring 的东西,例如对 JDK 方法或构造函数的调用。
拦截paint
方法@After
绘图已经完成对你也没有帮助。即使你拦截它 @Before
绘图完成了,它也不会帮助你,因为 Graphics2D
对象只是一个助手,TextLayout.draw
的一个参数。因为 TextLayout
对象,根据 API 的描述,是不可变的,你必须挂钩它的构造函数调用并修改给它的 String
参数。这是一个丑陋的 hack,但如果您在运行时为 JAR 设置编译时二进制织入或加载时织入,那么对于 AspectJ 绝对可行。
如果你能给我看更多代码或告诉我哪个 JAR 以何种方式使用,我可以更具体地回答,如果这个回复对你来说不是太技术性的话。
P.S.: 如果你描述了你真正想要达到的目标而不去想如何你认为你应该在第一时间做它也许会更好地方。也许有更简单的方法。
最后,我用Javassist解决了这个问题。因为 TextLayout 是不可变的,所以不可能更改它的值。因此,最好的解决方案(我认为)是重命名当前的 paint 方法并使用 Javassist 创建一个新方法。因此,在 运行 时间内,调用了我的新方法而不是原来的方法。代码如下:
CtClass clas = ClassPool.getDefault().get("classFullName");
CtMethod mold = clas.getMethod("MethodName", "MethodParameters");
//Rename the original method name
String nname = mname+"$impl";
mold.setName(nname);
CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
String bodyText = "New Method body";
StringBuffer body = new StringBuffer();
body.append(bodyText);
//Replace the body of the intercepter method with generated code block and add it to class.
mnew.setBody(body.toString());
clas.addMethod(mnew);
clas.writeFile();
clas.toClass();