AspectJ:尝试拦截对象创建时出现 ClassCastException [英] AspectJ: ClassCastException when trying to intercept object creation

查看:34
本文介绍了AspectJ:尝试拦截对象创建时出现 ClassCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图拦截遗留代码中的对象创建以返回另一个对象.

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 工作很好".这也可以解释为什么扩展可以解决问题,因为右侧仍然具有正确的类型 (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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆