2

私は AspectJ を使用して LTW をセットアップし、かなり迅速かつ成功しました。セットアップは次のとおりです: beans.xml:

<context:annotation-config />
<aop:aspectj-autoproxy />
<context:spring-configured />
<context:load-time-weaver />
<context:component-scan base-package="com.test.service" />

クラスに自動配線される私のサービス:

@Service
public class MyService {
}

親クラス:

public class Bar {
}

サービスを自動配線し、Bar を拡張する構成可能なクラス。

@Configurable
public class BarExtended extends Bar{
    @Autowired
    private MyService service;
    public MyService getWeavedInObject(){
        return service;
    }
}

そして、親クラス Bar への参照を持つクラスのみ:

public class Foo {
    private Bar bar;
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

そして成功したテストケース。BarExtended のインスタンスを作成し、LTW が機能しているかどうかを確認するだけです。Foo クラスは何もしません。

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

このテストは緑色で実行されます。しかし、次のテストは失敗します:

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

クラス BarExtended が Foo に設定されている行を挿入するだけです。ダウンキャストにより、AspjectJ が機能しなくなります。

ところで、Foo クラスを BarExtended クラスを使用するように変更すると (したがって、アップキャストは必要ありません):

public class Foo {
    private BarExtended bar;
    public void setBar(BarExtended bar) {
        this.bar = bar;
    }
}

上記のテストは機能します。構成可能なオブジェクトがアップキャストされたときに、なぜ AspjectJ が非常に奇妙な動作をするのか、誰にもわかりますか?

編集:以下も失敗します:

@Test
public void simple() {
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    Bar bar = (Bar) new BarExtended();
    foo.setBar(bar);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

別の BarExtended オブジェクトが Foo に設定され、最初の barExtended オブジェクトは AspectJ によって無視されます。しかし、リフレクションを使用して BarExtended をインスタンス化すると、次のようになります。

@Test
public void simple() throws InstantiationException, IllegalAccessException{
    Foo foo = new Foo();
    Bar barExtended = (Bar) BarExtended.class.newInstance();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", ((BarExtended)barExtended).getWeavedInObject());
}

奇妙ですね。

どうもありがとう

よろしく、

アンドレアス

4

2 に答える 2

1

過去に、LTW が構成されていると思っていた問題がありましたが、それはよくわからない理由によるものではありませんでした。したがって、構成ファイルに次の変更を加えて、すべてが機能するかどうかを確認してください。

  <context:load-time-weaver aspectj-weaving="on" />

<aop:aspectj-autoproxy />LTWが実際に実行されている必要がない場合は、構成から削除してください。

JUnit テストを実行するとき、LTW エージェントの場所を JUnit に伝えるために vm 引数を渡しますか? そうでない場合は、LTW が実行されていません。

これがドキュメントの内容です<context:load-time-weaver />

「loadTimeWeaver」という名前の Bean として使用可能な、このアプリケーション コンテキストの Spring LoadTimeWeaver をアクティブにします。LoadTimeWeaverAware インターフェースを実装するすべての Bean は、LoadTimeWeaver 参照を自動的に受け取ります。たとえば、Spring の JPA ブートストラップ サポート。デフォルトのウィーバーは自動的に決定されます。Spring 2.5 以降: Sun の GlassFish、Oracle の OC4J、Spring の VM エージェント、および Spring の ReflectiveLoadTimeWeaver によってサポートされる任意の ClassLoader (TomcatInstrumentableClassLoader など) を検出します。AspectJ ロードタイム ウィービングのアクティブ化は、Spring の LoadTimeWeaver を通じて登録された AspectJ クラス トランスフォーマーを使用して、単純なフラグ (「aspectj-weaving」属性) を介して指定されます。「META-INF/aop. これにより、Spring Bean ファクトリの外部でインスタンス化された非管理クラス (通常は @Configurable アノテーションが付けられたクラス) に依存性注入を適用するための現在のアプリケーション コンテキストもアクティブ化されます。これは、AnnotationBeanConfigurerAspect がクラスパス (つまり、spring-aspects.jar) にある場合にのみ発生し、デフォルトで「spring-configured」を効果的にアクティブ化します。ロード時のウィービング サポートのブートストラップに代わるコードベースの方法については、org.springframework.context.annotation.EnableLoadTimeWeaving の Javadoc を参照してください。これにより、Spring Bean ファクトリの外部でインスタンス化された非管理クラス (通常は @Configurable アノテーションが付けられたクラス) に依存性注入を適用するための現在のアプリケーション コンテキストもアクティブ化されます。これは、AnnotationBeanConfigurerAspect がクラスパス (つまり、spring-aspects.jar) にある場合にのみ発生し、デフォルトで「spring-configured」を効果的にアクティブ化します。ロード時のウィービング サポートのブートストラップに代わるコードベースの方法については、org.springframework.context.annotation.EnableLoadTimeWeaving の Javadoc を参照してください。

つまり、要約<context:load-time-weaver />すると、loadTimeWeaver の ID を持つ Bean を定義し、aop.xml などの特別なファイルを探してクラス パスをスキャンして、aspectJ をオンにする必要があるかどうかを判断することについてのようです。なんらかの理由でアスペクトJをオンにできない場合、aspectJが確実にオンになっていることを確認するにaspectj-weaving="on"は、起動時に失敗するように設定する必要があります。これはまさにあなたが望むものです。私のWebアプリには、Webアプリの起動時に実行するテストがあり、aspectJが実行されていることを確認し、そうでない場合は文句を言います。

于 2012-07-02T08:51:51.033 に答える