AspectJ:尝试拦截对象创建时的ClassCastException [英] AspectJ: ClassCastException when trying to intercept object creation
问题描述
我试图拦截旧版代码中的对象创建以返回另一个对象.
I'm trying to intercept object creation in legacy code to return another object.
我的示例代码:
public class ObjectCreationTest {
interface A {
String say();
}
public static class MyImpl implements A {
@Override
public String say() {
return "MyImpl";
}
}
public static class YourImpl implements A {
@Override
public String say() {
return "YourImpl";
}
}
public static void main(String[] args) {
A obj = new MyImpl();
System.out.println(obj.getClass());
System.out.println(obj.say());
}
}
@Aspect
public class MyAspect {
@Around(value = "call(com.leon.test.ObjectCreationTest$MyImpl.new(..))")
public Object initAdvice(ProceedingJoinPoint pjp) throws Throwable {
return new ObjectCreationTest.YourImpl();
}
}
但是,我得到了
Exception in thread "main" java.lang.ClassCastException: com.leon.test.ObjectCreationTest$YourImpl cannot be cast to com.leon.test.ObjectCreationTest$MyImpl
at com.leon.test.ObjectCreationTest.main(ObjectCreationTest.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
仅当我将YourImpl更改为从MyImpl扩展时,它才有效. (但这不是我所期望的)
Only when I change YourImpl to extends from MyImpl, it works. (but this is not what I expected)
只是想知道有什么错误或根本不可行吗?
Just wondering is there anything wrong or just not doable?
谢谢
推荐答案
恐怕似乎不可能.强制转换似乎发生在对象创建与分配给行A obj = new MyImpl();
的右侧之间,因为返回null会产生'fine'作用.这也可以解释为什么扩展可以解决此问题,因为右侧仍将具有正确的类型(MyImpl
).
Appears to be impossible I'm afraid. The cast seems to be happening between object creation and assignment to the right hand side of the line A obj = new MyImpl();
, since returning null works 'fine'. That would also explain why extending fixes the problem, since the right side will then still have the correct type (MyImpl
).
这意味着存在一种解决方法,方法是隐藏构造函数并提供静态实例化方法,该方法返回 Interface 类型的对象作为实例化MyImpl的唯一方法.最终看起来很粗糙:
This means a workaround exists by hiding the constructor and offering a static instantiation method which returns an object of the Interface type as the only way of instantiating MyImpl. This ends up looking rather crude though:
public class ObjectCreationTest {
public static void main(final String[] args) {
A obj = MyImpl.instance();
System.out.println(obj.getClass());
System.out.println(obj.say());
}
}
public class MyImpl implements A {
public static A instance() {
return new MyImpl();
}
private MyImpl() {
}
@Override
public String say() {
return "MyImpl";
}
}
然后,您让自己的方面捕获对该方法instance()
的调用:
Then you let your aspect catch calls to that instance()
-method:
@Aspect
public class MyAspect {
@Around(value = "call(A com.oneandone.MyImpl.instance(..))")
public Object initAdvice(final ProceedingJoinPoint pjp) throws Throwable {
return new YourImpl();
}
}
不确定这是否仍然适用于您的用例,但我认为这是与您一开始尝试的最接近的工作方式.
Not sure if this is still applicable to your usecase, but I think it's the closest working thing to what you were attempting in the first place.
这篇关于AspectJ:尝试拦截对象创建时的ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!