Java 可以用AspectJ替换抽象类吗
给定Java 可以用AspectJ替换抽象类吗,java,abstract-class,aspectj,Java,Abstract Class,Aspectj,给定java.util.Timer您可以执行以下操作: // where TimerMock extends Timer Timer around(): call (Timer.new()) { return new TimerMock(); } 这是否可能与抽象类有关?以java.util.TimerTask为例,它是一个具有以下签名的抽象类: public abstract class TimerTask implements Runnable { (...) pu
java.util.Timer
您可以执行以下操作:
// where TimerMock extends Timer
Timer around(): call (Timer.new()) {
return new TimerMock();
}
这是否可能与抽象类有关?以java.util.TimerTask
为例,它是一个具有以下签名的抽象类:
public abstract class TimerTask implements Runnable {
(...)
public abstract void run();
}
是否可以返回扩展TimerTask的类?
如何匹配?您将很难正确匹配连接点
让我用你最初的例子来解释这些问题:
public aspect InterceptTimer
{
// where TimerMock extends Timer
Timer around(): call(Timer.new())
{
return new TimerMock();
}
}
public class Test {
public void method()
{
Timer a = new Timer();
System.out.println(a.toString());
}
}
在编织之后,AspectJ将替换计时器a=new Timer()对于语义上等同于Timer a=new TimerMock()的事物,code>代码>哪个工作正常
然而,对于抽象类,事情并不是那么顺利。在本例中,您希望用具体类替换抽象类的具体实现。这样做的一个方面可能类似于(假设现在TimerMock扩展了TimerTask):
“TimerTask+”
确保您拦截扩展TimerTask的所有类,并且“!in(InterceptTimer)”
确保切入点不会拦截连接点“new TimerMock();”
,这将导致无限递归
现在让我们假设您有一个具体的类:
public class MyTimer extends TimerTask {
@Override
public void run()
{
// ...
}
}
如果要拦截以下创建:
public void method() {
MyTimer a = new MyTimer();
a.run();
}
您会立即看到错误:
"
应用于构造函数调用的不兼容返回类型(void
test.MyTimer()
"
这是因为连接点“new MyTimer()”在词汇上与“TimerTask”不同。如果您可以通过“new TimerTask()”来更改“new MyTimer()”连接点,那么它将起作用,但是,您不能这样做,因为TimerTask是一个抽象类
如果你想聪明一点,把“建议”改为:objectaround():call(MyTask+.new())&&!在(截取计时器){…}
您不会得到编译错误,而是运行时错误:
"java.lang.ClassCastException: test.TimerMock cannot be cast to test.MyTimer"
这是因为在编织过程中,AspectJ将执行以下操作:MyTimer a=(MyTimer)new TimerMock()代码>
我认为不可能做你想做的事情,至少不能用这种方法,也许有一种方法可以利用“执行”和“调用”连接点之间的差异来做到这一点。Thks了解详细程度!
"java.lang.ClassCastException: test.TimerMock cannot be cast to test.MyTimer"