2016-08-20 1 views
0

私はMyClassAopLoggerです。 doSomethingに例外がある場合、反復は停止します。Spring AOPは投げた後に反復を続けます

logAroundに存在しないようにして、次のホストに進む方法はありますか? ObjectlogAroundで返されましたが、これで何ができますか?Object

class MyClass{ 
    void check() throws Exception {  
     Iterator<Host> iter_host = configReader.getHostMap().values().iterator();  
     while (iter_host.hasNext()) {    
      Host host = (Host) iter_host.next(); 
      host.doSomething(); 
     } 
    } 
    void doSomething(){} //Exception 
} 

class AopLogger {  
    @Around("execution(* com.mypackage..*.*(..))") 
    Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ 
     return proceedingJoinPoint.proceed(); 
    } 
} 
+0

あなたは十分な情報を提供していません。ジョインポイントがdoSomethingメソッド(publicであると仮定)にある場合、try catching blockをreturn proceedingJoinPoint.proceed()の周りに置くだけで十分です。 "それは何のために良いのですか?" doSomethingを入力すると、メソッドが戻るときにログに記録されることがあります。実際にはこれがあなたのコードにないことは奇妙です。 –

+0

私はtry catch catchブロックを置くときに、proceedingJoinPoint.proceed()の反復が終了し、アプリケーションが終了します。私がtry.getSoolean()の周りにtry catchブロックを置くと、反復は続行されますが、logAroundに何も記録できません。 – user2683906

+0

まずjoinpointを見つけてください:return proceedingJoinPoint.proceed()およびProceedingJoinPointのさまざまなフィールドを調べます。どのメソッドが傍受されているかを確認する必要があります。そこから推理しよう。 –

答えて

1

まず、アスペクトクラスには、@Aspectアノテーションが必要です。第2に、Spring AOPを使用し、AspectJを完全に使用しない場合は、アスペクトおよびすべてのターゲットクラスもSpring @Componentである必要があります。

と言えば、ここでは少しサンプルです。プレーンなAspectJで作成しましたが、アスペクトコードはSpring AOPで同じにする必要があります。

ヘルパークラスコードのコンパイルを行い、実行するために:

package de.scrum_master.app; 

import java.util.Random; 

public class Host { 
    private static final Random RANDOM = new Random(); 

    private String name; 

    public Host(String name) { 
     this.name = name; 
    } 

    public void doSomething() { 
     if (RANDOM.nextBoolean()) 
      throw new RuntimeException("oops!"); 
    } 

    @Override 
    public String toString() { 
     return "Host(name=" + name + ")"; 
    } 
} 
package de.scrum_master.app; 

import java.util.HashMap; 
import java.util.Map; 

public class ConfigReader { 
    private Map<Integer, Host> hostMap = new HashMap<>(); 

    public ConfigReader() { 
     hostMap.put(1, new Host("mercury")); 
     hostMap.put(2, new Host("venus")); 
     hostMap.put(3, new Host("earth")); 
     hostMap.put(4, new Host("mars")); 
    } 

    public Map<Integer, Host> getHostMap() { 
     return hostMap; 
    } 
} 

ドライバアプリケーション:

私は古いJDKのバージョンからの遺物であるIteratorを好きではなかったです、だから私はより現代的なJavaスタイルforループに置き換えました。ポイントカット/アドバイスを同時に扱うロギングと例外をやってと

package de.scrum_master.app; 

class MyClass { 
    private ConfigReader configReader = new ConfigReader(); 

    void check() throws Exception { 
     for (Host host : configReader.getHostMap().values()) { 
      System.out.println(host); 
      host.doSomething(); 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     new MyClass().check(); 
    } 
} 

アスペクト比:

また、コードの最後で私のコメントを注意してください。

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

@Aspect 
public class AopLogger { 
    private static final InheritableThreadLocal<String> indent = new InheritableThreadLocal<String>() { 
     @Override 
     protected String initialValue() { 
      return ""; 
     } 
    }; 

    @Around("execution(* de.scrum_master.app..*(..)) && !execution(* toString())") 
    public Object logAround(ProceedingJoinPoint thisJoinPoint) throws Throwable { 
     Object result = null; 
     System.out.println(indent.get() + ">> " + thisJoinPoint); 
     try { 
      indent.set(indent.get() + " "); 
      result = thisJoinPoint.proceed(); 
      indent.set(indent.get().substring(2)); 
     } catch (Exception e) { 
      System.out.println(indent.get() + "Caught exception: " + e); 
      indent.set(indent.get().substring(2)); 
     } 
     System.out.println(indent.get() + "<< " + thisJoinPoint); 

     // Attention: If a method with a caught exception does not have 'void' 
     // return type, we return a (probably unexpected) result of 'null' here. 
     // So maybe we should not catch all execptions but rather pick more 
     // specific joinpoints where we are sure we can cleanly handle the 
     // corresponding exceptions. 
     return result; 
    } 
} 

コンソールログ:例外処理からログを分離

>> execution(void de.scrum_master.app.MyClass.main(String[])) 
    >> execution(void de.scrum_master.app.MyClass.check()) 
    >> execution(Map de.scrum_master.app.ConfigReader.getHostMap()) 
    << execution(Map de.scrum_master.app.ConfigReader.getHostMap()) 
Host(name=mercury) 
    >> execution(void de.scrum_master.app.Host.doSomething()) 
     Caught exception: java.lang.RuntimeException: oops! 
    << execution(void de.scrum_master.app.Host.doSomething()) 
Host(name=venus) 
    >> execution(void de.scrum_master.app.Host.doSomething()) 
    << execution(void de.scrum_master.app.Host.doSomething()) 
Host(name=earth) 
    >> execution(void de.scrum_master.app.Host.doSomething()) 
     Caught exception: java.lang.RuntimeException: oops! 
    << execution(void de.scrum_master.app.Host.doSomething()) 
Host(name=mars) 
    >> execution(void de.scrum_master.app.Host.doSomething()) 
     Caught exception: java.lang.RuntimeException: oops! 
    << execution(void de.scrum_master.app.Host.doSomething()) 
    << execution(void de.scrum_master.app.MyClass.check()) 
<< execution(void de.scrum_master.app.MyClass.main(String[])) 

第二の態様の変種:

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

@Aspect 
public class AopLogger { 
    private static final InheritableThreadLocal<String> indent = new InheritableThreadLocal<String>() { 
     @Override 
     protected String initialValue() { 
      return ""; 
     } 
    }; 

    @Around("execution(* de.scrum_master.app..*(..)) && !execution(* toString())") 
    public Object logAround(ProceedingJoinPoint thisJoinPoint) throws Throwable { 
     System.out.println(indent.get() + ">> " + thisJoinPoint); 
     try { 
      indent.set(indent.get() + " "); 
      Object result = thisJoinPoint.proceed(); 
      indent.set(indent.get().substring(2)); 
      System.out.println(indent.get() + "<< " + thisJoinPoint); 
      return result; 
     } catch (Exception e) { 
      indent.set(indent.get().substring(2)); 
      System.out.println(indent.get() + "<< " + thisJoinPoint); 
      throw e; 
     } 
    } 

    @Around("execution(void de.scrum_master.app.Host.doSomething())") 
    public void handleException(ProceedingJoinPoint thisJoinPoint) throws Throwable { 
     try { 
      thisJoinPoint.proceed(); 
     } catch (Exception e) { 
      System.out.println(indent.get() + "Caught exception: " + e); 
     } 
    } 
} 

ログ出力は、例外処理を同じまま、今回より正確なポイントカットを持つ別のアドバイスにあります。ロギングアドバイスはロギングのみを扱います(正しいインデント用でない場合はtry-catchは必要ありません)。例外処理のアドバイスは、自分の仕事だけを行います。

お気軽にフォローアップの質問をしてください。

+0

ありがとう、私は問題がApache BasicDataSourceと思う。メソッドdosomethingは、jdbcプールを作成します。メソッドcheck()は、ホストに到達できない場合に終了します。 try()catchブロックにcheck()を置くと、それは機能します。私はrunnableクラスで同じことをやっている別の方法を試していますが、例外をスローするvoid run()メソッドの実装方法がわかりません。私はvoid run()が例外をスローすることを意味する – user2683906

関連する問題