Springaop-implementations

提供:Dev Guides
移動先:案内検索

Spring AOP-実装

Springは、カスタムアスペクトを実装するために* @ AspectJアノテーションスタイル*アプローチと*スキーマベース*アプローチをサポートしています。

XMLスキーマベース

アスペクトは、XMLベースの構成とともに通常のクラスを使用して実装されます。

このセクションで説明されているAOP名前空間タグを使用するには、次のように説明されている春のAOPスキーマをインポートする必要があります-

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"

   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns:aop = "http://www.springframework.org/schema/aop"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <!-- bean definition & AOP specific configuration -->

</beans>

アスペクトを宣言する

*aspect* は *<aop:aspect>* 要素を使用して宣言され、バッキングBeanは次のように *ref* 属性を使用して参照されます。
<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

ここでは、前の章で見たように、他のSpring Beanと同じように「aBean」が構成され、依存関係が注入されます。

PointCutの宣言

*PointCut* は、結合ポイント(つまり、 メソッド)さまざまなアドバイスを使用して実行します。 XML Schemaベースの構成で作業中、PointCutは次のように定義されます-
<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.xyz.myapp.service.*.*(..))"/>
      ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

次の例では、com.finddevguidesパッケージのStudentクラスで使用可能なgetName()メソッドの実行と一致する「businessService」という名前のPointCutを定義しています。

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.finddevguides.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

アドバイスの宣言

次のように<aop:\ {ADVICE NAME}>要素を使用して、<aop:aspect>内で5つのアドバイスのいずれかを宣言できます。

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
      <aop:PointCut id = "businessService"
         expression = "execution(* com.xyz.myapp.service.*.*(..))"/>

      <!-- a before advice definition -->
      <aop:before PointCut-ref = "businessService"
         method = "doRequiredTask"/>

      <!-- an after advice definition -->
      <aop:after PointCut-ref = "businessService"
         method = "doRequiredTask"/>

      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning PointCut-ref = "businessService"
         returning = "retVal"
         method = "doRequiredTask"/>

      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing PointCut-ref = "businessService"
        throwing = "ex"
         method = "doRequiredTask"/>

      <!-- an around advice definition -->
      <aop:around PointCut-ref = "businessService"
         method = "doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

同じ doRequiredTask または異なるアドバイスに異なるメソッドを使用できます。 これらのメソッドは、アスペクトモジュールの一部として定義されます。

@AspectJベース

@AspectJは、アスペクトをJava 5アノテーションが付けられた通常のJavaクラスとして宣言するスタイルを指します。 @AspectJは、アスペクトをJava 5アノテーションが付けられた通常のJavaクラスとして宣言するスタイルを指します。 @AspectJサポートは、XMLスキーマベースの構成ファイル内に次の要素を含めることで有効になります。

<aop:aspectj-autoproxy/>

アスペクトを宣言する

アスペクトクラスは他の通常のBeanと同様であり、次のように@Aspectアノテーションが付けられることを除いて、他のクラスと同様にメソッドとフィールドを持つことができます。

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

次のように、他のBeanと同様にXMLで構成されます。

<bean id = "myAspect" class = "org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>

PointCutの宣言

*PointCut* は、結合ポイント(つまり、 メソッド)さまざまなアドバイスを使用して実行します。 @AspectJベースの構成で作業中、PointCut宣言には2つの部分があります-
  • 対象のメソッド実行を正確に決定するPointCut式。
  • 名前と任意の数のパラメーターで構成されるPointCut署名。 メソッドの実際の本体は無関係であり、実際には空である必要があります。

次の例では、パッケージcom.xyz.myapp.serviceの下のクラスで使用可能なすべてのメソッドの実行に一致する「businessService」という名前のPointCutを定義します。

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.xyz.myapp.service.*.*(..))")//expression
private void businessService() {} //signature

次の例では、パッケージcom.finddevguidesのStudentクラスで使用可能なgetName()メソッドの実行と一致する「getname」という名前のPointCutを定義しています。

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.finddevguides.Student.getName(..))")
private void getname() {}

アドバイスの宣言

以下に示す@ \ {ADVICE-NAME}アノテーションを使用して、5つのアドバイスのいずれかを宣言できます。 これは、PointCut署名メソッドbusinessService()が既に定義されていることを前提としています。

@Before("businessService()")
public void doBeforeTask(){
   ...
}

@After("businessService()")
public void doAfterTask(){
   ...
}

@AfterReturning(PointCut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal){
  //you can intercept retVal here.
   ...
}

@AfterThrowing(PointCut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex){
  //you can intercept thrown exception here.
   ...
}

@Around("businessService()")
public void doAroundTask(){
   ...
}

任意のアドバイスに対してPointCutインラインを定義できます。 以下は、アドバイスの前にインラインPointCutを定義する例です。

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
   ...
}