2016-09-16 8 views
0

私は一般的にAspectJとAOPのかなり新しいです。 AspectJには、メソッドが呼び出される前、呼び出された後、返された後、例外がスローされた時など、多くのアノテーション(After、AfterReturningなど)があることがわかります。それはかなり典型的な使用例であるロギングのためです。私はこの記事を見てきました。私はそれが私が必要とするものの大部分だと思います。これはAspectJと "jcambi aspect"を使ってロギングを実行します。AspectJを使用してさまざまなデータを条件付きでログに記録する方法

しかし、私は、次のような何かをしたいと思います:

public void login(User user) { 
    String userType = user.getType(); 

    if (!user.isActive()) { 
    // point cut 1 -- log inactive user 
    } else if (!user.isPasswordValid()) { 
    // point cut 2 -- log wrong password 
    } else { 
     // point cut 3 -- log successful login 
    } 
} 

我々が確立ログフォーマットを持っています。何かのように:

<actor>|<action_code>|<error_code>|<extra_info> 

すべてのアクタータイプ、アクションおよびエラーコードは列挙型に含まれています。何が起こったかに応じて、「IFSの内

ログ、および ログ異なる情報:

にAspectJのを指示する方法はありますか?例えば、点1つのログ次のいずれかの切断:

admin|login|001|Admin user inactive 
user|login|001|Normal user inactive 

を...点で2ログ次のいずれかの切断:

admin|login|002|Invalid Admin password 
user|login|002|Invalid normal user password 

を...点で3ログを切断次のいずれか:

admin|login|000|Successful Admin login 
user|login|000|Successful Normal user login 

何かが私にはありません。または少なくとも簡単ではない。しかし、試行する価値があるかどうかはわかりません。だから私は破れている。一方では、すべてのロギングのコードを「サニタイズ」したいと思います。一方、これを実装するにはあまりにも多くの作業が必要かどうかはわかりません。

アイデア?

*************************************** EDIT ****** *********************************

は、両方のあなたの答えをありがとう!私は今、二つのことを理解しています:1.私は、私の前に多くの仕事を持っています。そして、私は "ログイン"の例をあまり重視しないと思います。

ログインはただ一つの小さなユースケースです。私の仕事は、多くの、多くのクラスのメソッドの束に...どこでもログを追加することです。基本的にどこでもアプリケーションのどこにでもLOG.debug()やLOG.info()があり、Aspectのログに置き換えられます。これはまた、私が望むだけで、私の人生を楽にするためにすべてのコードをリファクタリングすることはできません。私はログインが例外を使用するようにしたいと思うが、私の仕事の範囲を超えている:ロギングを追加する。

そしてもちろん、それぞれの方法でビジネスロジックは異なる、そのようになりますので、ログはなります。だから私の質問になる:これを行うベストプラクティスは何ですか?つまり、それぞれの方法は独自のロジックとif if ...を持ち、条件付きで別のものを記録します。だから私は先に進み、これらのユースケースのそれぞれについてアスペクトクラスを作成し、基本的にそこに同じ "ifs"を持っていますか?

例(つまり、ログインできませんよ!):データをインポートする方法。

public void import(String type) { 
     if (type.equals("people")) { 
     try { 
      int result = importPeople(); 
      if (result > 0) { 
      // do some stuff 
      LOG.info("ok"); 
      } else { 
      // do some stuff 
      LOG.info("problem"); 
      } 
     } catch (Exception e) { 
      // do some stuff 
      LOG.debug("exception ..."); 
     } 
     } else if (type.equals("places")) { 
     try { 
      int result = importPlaces(); 
      if (result > 0) { 
      // do some stuff 
      LOG.info("ok"); 
      } else { 
      // do some stuff 
      LOG.info("problem"); 
      } 
     } catch (Exception e) { 
      // do some stuff 
      LOG.debug("exception ..."); 
     } 
     } 
    } 

繰り返しコードなどがありますが、あなたは考えが分かります。また、このメソッドをログに記録するために、 "import"アスペクトを作成する必要があります...付随するすべての "ifs"を "ok"、 "problem"、 "exception"をログに記録しますか?そして、の場合はすべてユースケースですか?

私はすべて侵入型のロギングコードを取り除いていますが、元のメソッドの両方でロジックを持たなければならないというコードの匂いのようです。この方法は、ログよりも多くのことをやっている)と対応するAspect ...

とにかく、あなたはどちらも私の元の質問に答えました...しかし、私はであることができます。答えです。彼はロットをそれに入れたように思われるので、kriegaexを受け入れるつもりです!

+0

申し訳ありません、記事へのリンクを忘れました: http://www.yegor256.com/2014/06/01/aop-aspectj-java-method-logging.html –

答えて

0

はい、それは可能です。しかし、もし私があなただったら、ちょっと違った話をしていきます。まず、未知のユーザーや非アクティブなユーザー、または間違ったパスワードのために、失敗したログインの例外をスローします。代わりに、loginメソッドはブール値を返すことができます(ログインに成功する場合はtrue、それ以外の場合はfalse)。しかし、私の意見では、これは現代のOOPよりもむしろ古風なCスタイルになります。

ここには一貫した例があります。多くの静的メンバーとメソッドを持つ醜いUserDBクラスには申し訳ありません。実際には、クリアテキストのパスワードは保存せず、無作為化された塩と塩漬けのハッシュを保存します。しかし、結局のところ、それはアスペクトベースの条件付きログのための概念の証明に過ぎません。ログインに使用

ユーザビーン:

package de.scrum_master.app; 

public class User { 
    private String id; 
    private String password; 

    public User(String id, String password) { 
     this.id = id; 
     this.password = password; 
    } 

    public String getId() { 
     return id; 
    } 

    public String getPassword() { 
     return password; 
    } 
} 

ユーザデータベース:

ハードコードされたDBエントリは、静的な列挙型、メンバーおよび方法ならびに簡単のために静的な内部クラスが存在します酒。ごめんなさい!より良いデザインで同じことをどうやって行うのかを簡単に想像することができます。

package de.scrum_master.app; 

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

public class UserDB { 
    public static enum Role { admin, user, guest } 
    public static enum Action { login, logout, read, write } 
    public static enum Error { successful_login, user_inactive, invalid_password, unknown_user } 

    private static class UserInfo { 
     String password; 
     Role role; 
     boolean active; 

     public UserInfo(String password, Role role, boolean active) { 
      this.password = password; 
      this.role = role; 
      this.active = active; 
     } 
    } 

    private static Map<String, UserInfo> knownUsers = new HashMap<>(); 

    static { 
     knownUsers.put("bruce", new UserInfo("alm1GHTy", Role.admin, true)); 
     knownUsers.put("john", new UserInfo("LetMe_in", Role.user, true)); 
     knownUsers.put("jane", new UserInfo("heLL0123", Role.guest, true)); 
     knownUsers.put("richard", new UserInfo("dicky", Role.user, false)); 
     knownUsers.put("martha", new UserInfo("paZZword", Role.admin, false)); 
    } 

    public static class UserDBException extends Exception { 
     private static final long serialVersionUID = 7662809670014934460L; 

     public final String userId; 
     public final Role role; 
     public final Action action; 
     public final Error error; 

     public UserDBException(String userId, Role role, Action action, Error error, String message) { 
      super(message); 
      this.userId = userId; 
      this.role = role; 
      this.action = action; 
      this.error = error; 
     } 
    } 

    public static boolean isKnown(User user) { 
     return knownUsers.get(user.getId()) != null; 
    } 

    public static boolean isActive(User user) { 
     return isKnown(user) && knownUsers.get(user.getId()).active; 
    } 

    public static boolean isPasswordValid(User user) { 
     return isKnown(user) && knownUsers.get(user.getId()).password.equals(user.getPassword()); 
    } 

    public static Role getRole(User user) { 
     return isKnown(user) ? knownUsers.get(user.getId()).role : null; 
    } 

    public static void login(User user) throws UserDBException { 
     String userId = user.getId(); 
     if (!isKnown(user)) 
      throw new UserDBException(
       userId, getRole(user), Action.login, 
       Error.unknown_user, "Unknown user" 
      ); 
     if (!isActive(user)) 
      throw new UserDBException(
       userId, getRole(user), Action.login, 
       Error.user_inactive, "Inactive " + getRole(user) 
      ); 
     if (!isPasswordValid(user)) 
      throw new UserDBException(
       userId, getRole(user), Action.login, 
       Error.invalid_password, "Invalid " + getRole(user) + " password" 
      ); 
    } 
} 

login(User)方法は、ロギングのために役立つ詳細と例外がスローされますどのように注意してください。いくつかのユーザ/パスワードの組み合わせのためにログインをシミュレートする

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

package de.scrum_master.app; 

import java.util.Arrays; 
import java.util.List; 

public class Application { 
    public static void main(String[] args) { 
     List<User> users = Arrays.asList(
      new User("mr_x", "foobar"), 
      new User("bruce", "foobar"), 
      new User("bruce", "alm1GHTy"), 
      new User("john", "foobar"), 
      new User("john", "LetMe_in"), 
      new User("jane", "foobar"), 
      new User("jane", "heLL0123"), 
      new User("richard", "foobar"), 
      new User("richard", "dicky"), 
      new User("martha", "foobar"), 
      new User("martha", "paZZword") 
     ); 

     for (User user : users) { 
      try { 
       UserDB.login(user); 
       System.out.printf("%-8s -> %s%n", user.getId(), "Successful " + UserDB.getRole(user) + " login"); 
      } catch (Exception e) { 
       System.out.printf("%-8s -> %s%n", user.getId(), e.getMessage()); 
      } 
     } 
    } 
} 

後のログイン失敗から出るのアプリケーションを回避するように、私達はちょうどキャッチし、すべての例外をログに記録しますのでご注意ください。

コンソールログ:

mr_x  -> Unknown user 
bruce -> Invalid admin password 
bruce -> Successful admin login 
john  -> Invalid user password 
john  -> Successful user login 
jane  -> Invalid guest password 
jane  -> Successful guest login 
richard -> Inactive user 
richard -> Inactive user 
martha -> Inactive admin 
martha -> Inactive admin 

ログインロガーアスペクト:

私はあなたが最初のように縦横のログとそれらを混同しないようにApplication.main(..)で2つのSystem.out.printf(..)呼び出しをコメントアウト示唆しています。側面のための

package de.scrum_master.aspect; 

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

import de.scrum_master.app.User; 
import de.scrum_master.app.UserDB; 
import de.scrum_master.app.UserDB.Action; 
import de.scrum_master.app.UserDB.Error; 
import de.scrum_master.app.UserDB.UserDBException; 

@Aspect 
public class UserActionLogger { 
    @Around("execution(void de.scrum_master.app.UserDB.login(*)) && args(user)") 
    public void captureLogin(ProceedingJoinPoint thisJoinPoint, User user) throws Throwable { 
     try { 
      thisJoinPoint.proceed(); 
      System.out.printf("%s|%s|%d03|%s%n", 
       user.getId(), Action.login, Error.successful_login.ordinal(), 
       "Successful " + UserDB.getRole(user) + " login" 
      ); 
     } catch (UserDBException e) { 
      System.out.printf("%s|%s|%03d|%s%n", 
       e.userId, e.action, e.error.ordinal(), 
       e.getMessage() 
      ); 
      throw e; 
     } 
    } 
} 

コンソールログ:

mr_x|login|003|Unknown user 
bruce|login|002|Invalid admin password 
bruce|login|003|Successful admin login 
john|login|002|Invalid user password 
john|login|003|Successful user login 
jane|login|002|Invalid guest password 
jane|login|003|Successful guest login 
richard|login|001|Inactive user 
richard|login|001|Inactive user 
martha|login|001|Inactive admin 
martha|login|001|Inactive admin 

のEtほら!これがあなたのおおよそのものであることを願っています。

0

可能です。 point-cut/withinのログインメソッドを作成し、アスペクトクラスでもユーザーオブジェクトを取得し、Userオブジェクトを取得すると条件付きでログを作成できます。 ユーザオブジェクトを取得するには、以下の回答の質問と、それがsurveyIdの値をどのように取得したかを確認してください.Userオブジェクトを取得する方法と同じです。ここで

@Around("updateDate()" 
public Object myAspect(final ProceedingJoinPoint pjp) { 

    //retrieve the runtime method arguments (dynamic) 
    Object returnVal = null; 
    for (final Object argument : pjp.getArgs()) 
    { 

     if (argument instanceof SurveyHelper) 
     { 
      SurveyHelper surveyHelper = (SurveyHelper) argument; 
      surveyId = surveyHelper.getSurveyId(); 

     } 

    } 
    try 
    { 
     returnVal = pjp.proceed(); 
    } 
    catch (Throwable e) 
    { 
     gtLogger.debug("Unable to use JointPoint :("); 
    } 
    return returnVal; 
} 

はあなたの参照のための完全なリンクです: Spring AOP for database operation

関連する問題