現在、プロジェクトに AspectJ を適用していますが、少し奇妙な動作を見つけました。
Q1: 型間宣言を使用して現在のクラスに新しいコンストラクターを追加しましたが、新しいコンストラクターを使用してクラスをインスタンス化すると、クラスのメンバー変数が初期化されないことがわかりました。
例えば:
新しいコンストラクターを追加するクラス:
public class Child {
public String name = "John";
public Child(String desc) {
// TODO Auto-generated constructor stub
}
}
アスペクトJコード:
public aspect MyTest {
public Child.new(String desc, int num) {
System.out.println("Child Name:" + this.name);
}
}
Child を新しいコンストラクターでインスタンス化すると、次のようになります。
new Child("A child", 5)
メンバ変数this.nameは、元のコンストラクタで行われるように初期化されません。
しかし、元のコンストラクターを呼び出すと、次のようになります。
new Child("A child")
メンバー変数this.nameは通常どおり「John」に初期化されます
結果:
子供の名前:null
これは AspectJ の制限ですか? とにかくこの問題を解決する方法はありますか?
メンバー変数の初期化のコードを新しいコンストラクターに追加したくありません。
Q2:新しく追加されたコンストラクターで、 super.method ()が正しく解決できないようです。
新しいコンストラクターを追加するクラス:
public class Child extends Parent{
public String name = "John";
public Child(String desc) {
}
}
ChildはParentを拡張します。親にはメソッドinit()があります
public class Parent {
public void init() {
//....
}
}
アスペクトにChildの新しいコンストラクターを追加します。
public aspect MyTest {
public Child.new(String desc, int num) {
super.init();
}
}
上記のアスペクト コードは例外をトリガーします。
Exception in thread "main" java.lang.NoSuchMethodError: com.test2.Child.ajc$superDispatch$com_test2_Child$init()V
at MyTest.ajc$postInterConstructor$MyTest$com_test2_Child(MyTest.aj:19)
at com.test2.Child.<init>(Child.java:1)
at MainProgram.main(MainProgram.java:11)
私の回避策は、クラスChildに別のメソッドを定義し、そのメソッド内で間接的に super.method() を呼び出すことです
たとえば、Childに対してsuper.init()を呼び出す新しいメソッドを追加します。
public void Child.initState()
{
super.init();
}
これで、以下のように新しく追加されたコンストラクターで initState() を呼び出すことができます。
public aspect MyTest {
public Child.new(String desc, int num) {
this.initState();
}
}
これは AspectJ の制限ですか? これがこの問題を解決する唯一の方法ですか?
お時間をいただきありがとうございました:)