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

查看:167
本文介绍了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会产生'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屋!

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