1

struts2、Spring IoC、およびTransasctions、jpa、Hibernateに基づく私のアプリでは、ユーザーが作成/更新された、またはチケットが作成されたなど、すべての重要なイベントを記録する「監査ログ機能」を導入したいと考えています誰かが開いた...
このログをデータベースに保存したいので、DAO を用意します。
ログに記録されたイベントが成功したかどうかに関係なく、イベントをログに記録したいという事実のために、この目的のために「AuditLogService」というサービス クラスも作成しました。ユーザーサービスに次のようなものがあります:

@Override
public boolean saveUser(UserDto userDto) {

    User u = new User();        
    u.setFirstName(userDto.getFirstName());
    u.setLastName(userDto.getLastName());
    u.setUserName(userDto.getUserName());       
    u.setPassword(userDto.getPassword());
    u.setIsLdapUser(userDto.getIsLdapUser());
    u.setId(userDto.getId());
    u.setAgentId(userDto.getAgentId());

    Boolean eventStatus = true;
        String event="";
    try{        
        if (u.getId()!=null){           
            dao.update(u);
            event = "UPDATE_USER";
        }else{
            dao.create(u);
            event = "CREATE_USER";          
        }           
    }catch (Exception e) {
        e.printStackTrace();
        eventStatus = false;
        return false;
    }
    finally {
        AuditLogEvent ale = auditLogEventDao.getAuditLogEvent(event);
        auditLogService.addAuditLogEvent(ale, eventStatus,u.toString());
    }

    return false;
}

監査ログ メソッドはユーザー保存メソッドをコミットする前に実行され、イベントが true であったと報告しますが、実際にはイベントは false でした。
どうすればこれを解決できますか?それとも、このアプローチは最善ではありません...?

  • アップデート!
    マイケルのアドバイスの後、私は自分のサービスをアスペクトにも変えました

    @Aspect  
    @Service
    class AuditLogAspectImpl implements AuditLogAspect {
        @Autowired
        private AuditLogDao dao;
    
    @Autowired
    private UserDao userDao;
    
    @Override
    @AfterReturning(pointcut = "execution(* xxx.yy.services..*.save*(..))", returning = "retVal")   
    public boolean afterLogEvent(JoinPoint joinPoint,Object retVal){
    }
    

    }

そして今、私はここのような私のメソッド署名を持っています. すべて正常に動作し、操作が失敗したか成功したかを検出でき、これをログ ファイルに記録できますが、これを dao クラスを介してデータベースからテーブルに記録したい場合は、操作が失敗し、トランザクションがロールされます。私の監査エントリが挿入されていません。
最初に、監査が必要な実際のメソッドと監査イベントの両方の操作が同じトランザクションコンテキストで実行されているため、これが発生していると考えました。そのうちの1つがロールバックされた場合、トランザクション全体がロールバックされ、アスペクト ロギング部分の新しいトランザクション。しかし、これはうまくいかないようです。

理由はありますか?

4

1 に答える 1

1

宣言型トランザクションはアラウンド アドバイス (AOP) を介して実装されているため、メソッド全体が実行され、最終的に監査ブロックが返され、トランザクションがコミットされるため、このアプローチは正しくありません。

監査やロギングなどは分野横断的な懸念の代表的な例であるため、独自の監査アスペクトを作成することをお勧めします。

Spring を使用したアスペクト指向プログラミングをご覧ください

失敗したものと成功したものを監査できるように、After (finally) のアドバイスを使用します。

実際にはそれほど複雑ではありません... AspectJ は必要ありません。Spring Aspects で十分です。

于 2012-07-25T08:27:21.963 に答える