69

ABC.javaで定義されている2つのメソッドがあります

public void method1(){
   .........
   method2();
  ...........
}


public void method2(){
  ...............
  ...............  
}

method2の呼び出しでAOPを使用したいので、メソッドcheckAccessでアスペクト機能を提供するAOPLogger.javaという1つのクラスを作成しました
。構成ファイルで、次のようにしました。

<bean id="advice" class="p.AOPLogger" />
<aop:config>
  <aop:pointcut id="abc" expression="execution(*p.ABC.method2(..))" />
  <aop:aspect id="service" ref="advice">
    <aop:before pointcut-ref="abc" method="checkAccess" />          
  </aop:aspect>
</aop:config>

しかし、私のmethod2が呼び出されたとき、AOP機能が呼び出されていません。つまり、 checkAccessメソッドがAOPLoggerクラスから呼び出されていません。

私が欠けているものはありますか?

4

14 に答える 14

89

アスペクトは、Beanを囲むプロキシに適用されます。Beanへの参照を取得するたびに、それは実際には構成で参照されるクラスではなく、関連するインターフェースを実装し、実際のクラスに委任し、AOPなどの機能を追加する合成クラスであることに注意してください。

上記の例では、クラスを直接呼び出していますが、そのクラスインスタンスがSpring Beanとして別のインスタンスに注入されると、プロキシとして注入されるため、メソッド呼び出しがプロキシで呼び出されます(アスペクトがトリガーされます)。 )。

上記を実現したい場合は、method1/method2を別々のBeanに分割するか、非スプリング指向のAOPフレームワークを使用できます。

Springのドキュメント(「AOPプロキシについて」のセクション)では、これといくつかの回避策(上記の最初の提案を含む)について詳しく説明しています。

于 2012-11-26T12:17:28.357 に答える
38

2022 年更新:

個人的には、こちらで説明されている TransactionHandler クラスを使用することを好みます。よりクリーンで柔軟な方法です。

元の答え:

セルフインジェクション使用で可能です。注入されたインスタンスを介して内部メソッドを呼び出すことができます:

@Component
public class Foo {
    @Resource
    private Foo foo;
    
    public void method1(){
        ..
        foo.method2();
        ..
    }
    public void method2(){
        ..
    }
}

Spring 4.3 以降、@Autowired を使用して実行することもできます。

4.3 以降、@Autowired は注入の自己参照、つまり現在注入されている Bean への参照も考慮します。

于 2016-08-30T14:48:27.420 に答える
8

Spring AOP フレームワークは「プロキシ」ベースです。AOP プロキシについてのドキュメントで詳しく説明されています。

Spring がアスペクト (この例では「ABC」など) で構成された Bean を構築すると、実際には実際の Bean のように機能する「プロキシ」オブジェクトが作成されます。プロキシは単に「実際の」オブジェクトへの呼び出しを委任しますが、この間接化を作成することにより、プロキシは「アドバイス」を実装する機会を得ます。たとえば、アドバイスはメソッド呼び出しごとにメッセージをログに記録できます。このスキームでは、実際のオブジェクト ("method1") 内のメソッドが同じオブジェクト (たとえば、method2) 内の他のメソッドを呼び出す場合、それらの呼び出しはプロキシなしで発生するため、アドバイスを実装する機会はありません。

あなたの例では、method1() が呼び出されると、プロキシは本来の処理を行う機会を得ることができますが、method1() が method2() を呼び出す場合、画像には何の側面もありません。ただし、me​​thod2 が他の Bean から呼び出された場合、プロキシはアドバイスを実行できます。

于 2012-11-26T19:54:12.633 に答える
6

私は同じ種類の問題を抱えていましたが、Spring を実装し、対応するメソッドを以下のように実装することで克服しましApplicationContextAwareBeanNameAware

class ABC implements ApplicationContextAware,BeanNameAware{

      @Override
      public void setApplicationContext(ApplicationContext ac) throws BeansException {
          applicationContext=ac;
      }

      @Override
      public void setBeanName(String beanName) {
          this.beanName=beanName;
      }
      private ApplicationContext applicationContext;
      private String beanName;
}

次に、同じクラスのメソッドを呼び出すときに置き換えましthis.た 。((ABC) applicationContext.getBean(beanName)).これにより、同じクラスのメソッドへの呼び出しがプロキシ経由でのみ発生することが保証されます。

だからmethod1()に変更

 public void method1(){
    .........
    ((ABC) applicationContext.getBean(beanName)).method2();
    ...........
  }

お役に立てれば。

于 2013-09-19T14:38:17.210 に答える
0

あなたが達成したいことは不可能です。説明は、SpringReferenceDocumentationにあります。

于 2012-11-26T12:17:45.677 に答える