3

次のようなJavaクラスがあります。

public class Foo{
   public void doSomething(){
     StageA a = new StageA();
     StageB b = new StageB();
     StageC c = new StageC();
     a.execute();
     b.execute();
     c.execute();
   }
}

さて、このクラス自体を実際に編集できないと仮定すると、Spring AOParoundを使用してexecuteメソッドのロギングを適用できますか?(おそらくaspect4jを使用せずに)

4

3 に答える 3

2

メソッドをログに記録することはできますが、(パフォーマンスのために)時間がかかりますが、メソッドが実行していることをログに記録することはできないと思います。

Spring Docsから:

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


メソッドの内部でlog4jロガーを使用している場合は、log4jを構成することで、メソッドが実行していることをログに記録できます。

(おそらくaspect4jを使用せずに)

->Springは内部で使用しますaspectJ

参考資料と例については、こちらを確認してください

于 2012-10-18T09:30:29.737 に答える
2

編集済み: FooクラスまたはStageクラスを変更せずに、各「execute」メソッドの実行をログに記録することはできないと思います。Stage...クラスはコンテナによって管理されていないためです。doSomethingメソッドが実行を開始するときにのみログに記録でき(FooクラスがSpringコンテナによって管理されている場合)、その実行フローを制御することはできません。

クラスをSpringコンテナで管理する場合は、これを簡単に行うことができます。Fooクラスではなく、Stage...クラスのSpringAOPの「アラウンド」アスペクトを記述するだけです。

単純なロギングの側面の例を次に示します。

@Component
@Aspect
@Order(value=2)
public class LoggingAspect {

    @Around("execution(* com.blablabla.server..*.*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass().getName());
        Object retVal = null;

        try {
            StringBuffer startMessageStringBuffer = new StringBuffer();

            startMessageStringBuffer.append("Start method ");
            startMessageStringBuffer.append(joinPoint.getSignature().getName());
            startMessageStringBuffer.append("(");

            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                startMessageStringBuffer.append(args[i]).append(",");
            }
            if (args.length > 0) {
                startMessageStringBuffer.deleteCharAt(startMessageStringBuffer.length() - 1);
            }

            startMessageStringBuffer.append(")");

            logger.trace(startMessageStringBuffer.toString());

            StopWatch stopWatch = new StopWatch();
            stopWatch.start();

            retVal = joinPoint.proceed();

            stopWatch.stop();

            StringBuffer endMessageStringBuffer = new StringBuffer();
            endMessageStringBuffer.append("Finish method ");
            endMessageStringBuffer.append(joinPoint.getSignature().getName());
            endMessageStringBuffer.append("(..); execution time: ");
            endMessageStringBuffer.append(stopWatch.getTotalTimeMillis());
            endMessageStringBuffer.append(" ms;");

            logger.trace(endMessageStringBuffer.toString());
        } catch (Throwable ex) {
            StringBuffer errorMessageStringBuffer = new StringBuffer();

             // Create error message 
             logger.error(errorMessageStringBuffer.toString(), e)

            throw ex;
        }

        return retVal;
    }
}
于 2012-10-18T09:37:08.683 に答える
1

はい、次のような名前のポイントカットターゲティングメソッドを使用して@Aroundアドバイスを書くことができます。executionexecute()

@Around("execution(* execute(..))")
public Object execute(ProceedingJoinPoint pjp) throws Throwable
{
    // Log statements before the call;

    Object obj = pjp.proceed();

    // Log statements after the call;

    return obj;
}
于 2012-10-18T09:40:45.863 に答える