以下是解释问题的代码段:
public class Demo {
// I want to enhance this method.
public String a() {
return "A";
}
// this method is not enhanced but the internal a() invocation should be
public String b() {
return "-> " + a();
}
}
我希望增强方法a()
,并且在调用方法b()
时,应执行增强的a()
。我猜CGLIB代理不费力。
此外,此增强操作应该是对象级别而不是类级别。
public static void verify() {
assert Objects.equals("-> A", new Demo().b());
assert !Objects.equals("-> A", enhance(new Demo()).b());
}
public static Demo enhance(Demo demo) {
throw new UnsupportedOperationException("I don't know how to do");
}
是否有解决此问题的解决方案?
顺便说一句:抱歉我的英语不好,但我认为我的意图很明确。补编:
实际上,我的问题是:
将记录异常堆栈跟踪,但其中一些使用detailMessage
在new XXException("sensitive")
字段中包含敏感数据,或者某些IOException
将打印详细的绝对路径。< / p>
printStackTrace()
将调用toString()
方法,toString()
方法将调用getMessage()
方法。 (您可以看到JDK源代码)
我想提供一个实用程序方法来包装/增强Exception
,让printStackTrace()
不打印敏感数据,但打印堆栈跟踪以查找错误。
然后可以安全地将这些Exception
对象发送到log4j。
答案 0 :(得分:2)
我没有看到只是子类化的问题。
await
您仍然可以使用它来代替正常的演示:
class EnhancedDemo extends Demo{
@Override
public String a(){
return "Enhanced A";
}
}
这还不够吗?难道你不能重构你认为需要的代码来代替dependency injection吗?
答案 1 :(得分:0)
正如您所提到的,CGLIB代理(和Java动态代理)都有相同的问题。当从代理方法调用另一个方法时(在你的情况下,当b()调用a())时,使用引用'self',代理永远不会进入图片。
作为一种解决方法,您可以考虑将代理对象本身传递给类,如此SO Answer。线程问你一个类似的问题,'增强'是Spring的事务处理代理。 之后,您可以使用对所有地方的引用而不是直接调用。
您也可以考虑重构您的代码,以免出现这种情况。但根据您的使用案例,可能会或可能不会这样。
关于enhancement action should be object-level rather than class-level
java动态代理在对象级别上工作的后一个问题。因此,如果您创建了该类的新对象而不对其进行代理,那么它将保持“无增强”。
答案 2 :(得分:0)
您似乎错误地接近了这个问题。 问题似乎不是&#34;如何动态更改垃圾&#34; &#34;如何正确设计我的代码以允许动态更改方法的实现&#34;。答案是:为方法实现策略模式功能。
以下是一个例子:
public interface MethodAStrategy
{
String methodAImplementation();
}
public class SimpleAStrategy
implements MethodAStrategy
{
public String methodAImplementation()
{
return "a";
}
}
public class EnhancedAStrategy
implements MethodAStrategy
{
public String methodAImplementation()
{
return "enhanced a";
}
}
public class EnhancedDemo
extends Demo
{
private MethodAStrategy strategyForMethodA;
private MethodAStrategy strategyForMethodB;
public EnhancedDemo()
{
strategyForMethodA = new SimpleAStrategy();
strategyForMethodB = new EnhancedAStrategy()
}
public String a()
{
return strategyForMethodA.methodAImplementation();
}
public String b()
{
return "->" + strategyForMethodB.methodAImplementation();
}
// as desired, add methods to change the strategies.
}
答案 3 :(得分:0)
由于您的真正问题是阻止将某些数据记录到文件中,最简单的方法是在日志记录点拦截此数据。扩展Log4J FileAppender
并重新编写绝对路径应该很容易。然后,您只需要确保使用自定义appender而不是常规appender,但这比您的想法更容易。