1概要

この記事では、Springで作成できるさまざまな種類のAOPアドバイスについて説明します。

  • アドバイス** は特定の参加ポイントでアスペクトによって取られる行動です。

さまざまな種類のアドバイスには、「前後」、「前」、「後」のアドバイスがあります。

側面の主な目的は、ロギング、プロファイリング、キャッシング、トランザクション管理などの分野横断的な問題をサポートすることです。

そして、ポイントカットの表現をもっと深く知りたいのなら、

昨日これらの紹介

をチェックしてください。


2アドバイスを有効にする

Springでは、AspectJアノテーションを使用してアドバイスを宣言できますが、最初に

@ EnableAspectJAutoProxy

アノテーションを設定クラスに適用する必要があります。これにより、AspectJの

@ Aspect

アノテーションでマークされたコンポーネントの処理のサポートが有効になります。

@Configuration
@ComponentScan(basePackages = {"org.baeldung.dao", "org.baeldung.aop"})
@EnableAspectJAutoProxy
public class TestConfig {
    ...
}


3アドバイスの前に

このアドバイスは、その名のとおり、結合点の前に実行されます。例外がスローされない限り、推奨されているメソッドの継続実行を妨げることはありません。

メソッド名が呼び出される前にログに記録するという、次の点を考慮してください。

@Component
@Aspect
public class LoggingAspect {

    private Logger logger = Logger.getLogger(LoggingAspect.class.getName());

    @Pointcut("@target(org.springframework.stereotype.Repository)")
    public void repositoryMethods() {};

    @Before("repositoryMethods()")
    public void logMethodCall(JoinPoint jp) {
        String methodName = jp.getSignature().getName();
        logger.info("Before " + methodName);
    }
}


logMethodCall

アドバイスは、

repositoryMethods

pointcutで定義されたリポジトリメソッドの前に実行されます。


4アドバイス後


@ After

アノテーションを使用して宣言したアドバイスの後、____は、例外がスローされたかどうかにかかわらず、一致したメソッドの実行後に実行されます。

いくつかの点で、それは

finally

ブロックに似ています。通常の実行の後にのみアドバイスをトリガーする必要がある場合は、

@ AfterReturning

アノテーションで宣言された

returnning advice

を使用する必要があります。ターゲットメソッドが例外をスローしたときにのみアドバイスをトリガーしたい場合は、

__ @ AfterThrowing


アノテーションを使用して宣言された

throwingアドバイスを使用する必要があります。


Foo

の新しいインスタンスが作成されたときに、いくつかのアプリケーションコンポーネントに通知したいとします。

FooDao

からイベントを公開することはできますが、これは単一の責任原則に違反します。代わりに、次の側面を定義することでこれを達成できます。

@Component
@Aspect
public class PublishingAspect {

    private ApplicationEventPublisher eventPublisher;

    @Autowired
    public void setEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Pointcut("@target(org.springframework.stereotype.Repository)")
    public void repositoryMethods() {}

    @Pointcut("execution(**  ** ..create** (Long,..))")
    public void firstLongParamMethods() {}

    @Pointcut("repositoryMethods() && firstLongParamMethods()")
    public void entityCreationMethods() {}

    @AfterReturning(value = "entityCreationMethods()", returning = "entity")
    public void logMethodCall(JoinPoint jp, Object entity) throws Throwable {
        eventPublisher.publishEvent(new FooCreationEvent(entity));
    }
}

まず、

@ AfterReturning

アノテーションを使用することで、ターゲットメソッドの戻り値にアクセスできることに注意してください。次に、__JoinPoint型のパラメータを宣言することで、ターゲットメソッドの呼び出しの引数にアクセスできます。

次に、単純にイベントを記録するリスナーを作成します。イベントの詳細については、

このチュートリアル

を参照してください。

@Component
public class FooCreationEventListener implements ApplicationListener<FooCreationEvent> {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Override
    public void onApplicationEvent(FooCreationEvent event) {
        logger.info("Created foo instance: " + event.getSource().toString());
    }
}


5アドバイスの周辺

  • アドバイスの周り** メソッド呼び出しなどのジョインポイントを囲みます。

これは最も強力な種類のアドバイスです。アラウンドアドバイスは、メソッド呼び出しの前後両方でカスタム動作を実行できます。独自の戻り値を提供するか、または例外をスローすることによって、ジョインポイントに進むか、推奨されているメソッドの実行を短縮するかを選択する責任もあります。

使い方を説明するために、メソッドの実行時間を測定したいとします。この目的のために、あなたは以下のアスペクトを作成することができます:

@Aspect
@Component
public class PerformanceAspect {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Pointcut("within(@org.springframework.stereotype.Repository ** )")
    public void repositoryClassMethods() {};

    @Around("repositoryClassMethods()")
    public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.nanoTime();
        Object retval = pjp.proceed();
        long end = System.nanoTime();
        String methodName = pjp.getSignature().getName();
        logger.info("Execution of " + methodName + " took " +
          TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
        return retval;
    }
}

このアドバイスは、

repositoryClassMethods

pointcutによって一致したジョインポイントのいずれかが実行されたときにトリガされます。

このアドバイスは

ProceedingJointPoint

型のパラメータを1つ取ります。パラメータは、ターゲットメソッドが呼び出される前にアクションを実行する機会を与えてくれます。この場合は、メソッドの開始時間を節約するだけです。

次に、ターゲットメソッドは任意の型の結果を返すことができるので、アドバイスの戻り型は

Object

です。ターゲットメソッドが

voidの場合、


null

が返されます。ターゲットメソッド呼び出しの後、タイミングを測定して記録し、メソッドの結果値を呼び出し元に返すことができます。


6. 概要

この記事では、Springでのさまざまな種類のアドバイスとその宣言および実装について学びました。スキーマベースのアプローチとAspectJアノテーションを使用してアスペクトを定義しました。私達はまたいくつかの可能なアドバイスアプリケーションを提供しました。

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-java[my githubプロジェクト]で見つけることができます – これはEclipseベースのプロジェクトです。そのままインポートして実行するのは簡単です。