Aspectjの@Before、@Afterを使ってメソッド前後にログ出力を入れる

spring

springにはAOPの概念があり、ビジネスロジックの本質とは異なった処理を別クラスに定義して、ビジネスロジックの実行前後などで共通処理として織り込む(インジェクションする)ことが出来ます。

@Before、@Afterは、springで使われる頻度の高いインジェクト方式です。
今回は基本的な@Before、@Afterの使い方を紹介していきます。

[スポンサーリンク]

目次

  1. 特定のパッケージを指定した@Beforeと@After
  2. 特定のパッケージ配下(サブクラスを含)全てを指定した@Beforeと@After
  3. 特定のクラスを指定した@Beforeと@After
  4. 特定のメソッドを指定した@Beforeと@After
  5. 特定の修飾子を指定した@Beforeと@After
  6. springでAOPを使うための各種xmlファイルの設定

特定のパッケージを指定した@Beforeと@After

パッケージ「com.example.service.impl」配下の全クラスの全メソッドが対象となります。
パッケージ「com.example.service.impl」配下のサブクラスは対象外です。

@Aspect
@Component
public class ExampleAspect {

	@Before("execution(* com.example.service.impl.*.*(..))")
	public void before() {
		System.out.println("このログは、メソッド処理「前」に実行しています。");
	}

	@After("execution(* com.example.service.impl.*.*(..))")
	public void after() {
		System.out.println("このログは、メソッド処理「後」に実行しています。");
	}

}

特定のパッケージ配下(サブクラスを含)全てを指定した@Beforeと@After

パッケージ「com.example.service.impl」配下の全クラスの全メソッドが対象となります。
パッケージ「com.example.service.impl」配下のサブクラスの全クラスの全メソッドが対象となります。

@Aspect
@Component
public class ExampleAspect {

	@Before("execution(* com.example..*.*(..))")
	public void before() {
		System.out.println("このログは、メソッド処理「前」に実行しています。");
	}

	@After("execution(* com.example..*.*(..))")
	public void after() {
		System.out.println("このログは、メソッド処理「後」に実行しています。");
	}

}

特定のクラスを指定した@Beforeと@After

クラス「com.example.service.impl.ExampleServoceImpl」の全メソッドが対象となります。

@Aspect
@Component
public class ExampleAspect {

	@Before("execution(* com.example.service.impl.ExampleServoceImpl.*(..))")
	public void before() {
		System.out.println("このログは、メソッド処理「前」に実行しています。");
	}

	@After("execution(* com.example.service.impl.ExampleServoceImpl.*(..))")
	public void after() {
		System.out.println("このログは、メソッド処理「後」に実行しています。");
	}

}

特定のメソッドを指定した@Beforeと@After

クラス「com.example.service.impl.ExampleServoceImpl」の「find」メソッドが対象となります。

@Aspect
@Component
public class ExampleAspect {

	@Before("execution(* com.example.service.impl.ExampleServoceImpl.find(..))")
	public void before() {
		System.out.println("このログは、メソッド処理「前」に実行しています。");
	}

	@After("execution(* com.example.service.impl.ExampleServoceImpl.find(..))")
	public void after() {
		System.out.println("このログは、メソッド処理「後」に実行しています。");
	}

}

特定の修飾子を指定した@Beforeと@After

パッケージ「com.example.service.impl」配下の全クラスのpublicメソッドが対象となります。
パッケージ「com.example.service.impl」配下のサブクラスの全クラスのpublicメソッドが対象となります。

@Aspect
@Component
public class ExampleAspect {

	@Before("execution(public * com.example..*.*(..))")
	public void before() {
		System.out.println("このログは、メソッド処理「前」に実行しています。");
	}

	@After("execution(public * com.example..*.*(..))")
	public void after() {
		System.out.println("このログは、メソッド処理「後」に実行しています。");
	}

}

springでAOPを使うための各種xmlファイルの設定

AOPを使うために、springの設定ファイル(servlet-context.xml)とmavenの設定ファイル(pom.xml)へ設定を追加します。
※mavenの設定ファイル(pom.xml)は依存ライブラリをmavenで管理している場合のみに限ります。

servlet-context.xmlの設定

マーカーのついている部分をservlet-context.xmlへ追加して下さい。

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
・
・
    <!-- AOPを使用するため以下を追加します。 -->
    <aop:aspectj-autoproxy/>
・
・
</beans:beans>

pom.xmlへ設定

cglibは、spring-aopの依存ライブラリなので追加する必要があります。

・
・
    <dependencies>
        <!-- aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2</version>
        </dependency>
    </dependencies>
・
・

最後に

@Before、@Afterをどこで動かすかについては「execution」で制御することが可能です。@Before、@Afterの使いどころは、「execution」の使い方をしっかりと押さえておけばOKです。

@Before、@Afterのサンプルでしたが、例外発生時やメソッド前後にも同じようにAspectjで処理をインジェクション出来るアノテーションが存在します。また@Before、@Afterでも通常のメソッド同様引数を受け取ることが出来ます。(これが出来ないとあまり役にたたないですよね。)
次回はこの辺りについてサンプルソースを作っていきたいと思います。