3

私はSpring / AOPのチュートリアルをいくつか経験しており、関連する概念にある程度慣れてきました。

今私の要件に来て、ログインしたユーザーのアクティビティを DB に保存するアクティビティ ログの実装を作成する必要があります。これは、サービスの申請や、ユーザーの場合の新しいユーザーの作成などに及ぶ可能性がありAdminます。注釈を持つ任意のメソッド (たとえば)、この情報は、、、など@ActivityLogの形式で永続化されます。actorIdactionCommentactionTimeactedUponId

ここで、POJO クラス ( ActivityLogDB 内のテーブルにマップされる) を作成し、このデータを内部から保存したい場合Advice(できればメソッドと同じトランザクションを使用し、メソッドは@Transactional注釈を使用します)、実際にどのように変数を設定しますか?このPOJO?? おそらくactorIdセッションオブジェクトから取得できます &actionTime単純にすることができますが、 /new Date()の動的な値はどうですか?actionCommentactedUponId

どんな助けも素晴らしいでしょう!(ところで、Hibernate Interceptor を使用しないという要件があります。)

4

3 に答える 3

3

完全な例を次に示します。

@Aspect
@Component
public class WebMethodAuditor {

protected final Log logger = LogFactory.getLog(getClass());

public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";

@Autowired
AuditRecordDAO auditRecordDAO; 

@Before("execution(* com.mycontrollers.*.*(..))")
public void beforeWebMethodExecution(JoinPoint joinPoint) {
    Object[] args = joinPoint.getArgs();
    String methodName = joinPoint.getSignature().getName();
    User principal = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    Timestamp timestamp = new Timestamp(new java.util.Date().getTime());
    // only log those methods called by an end user
    if(principal.getUsername() != null) {
        for(Object o : args) {
            Boolean doInspect = true;
            if(o instanceof ServletRequestDataBinder) doInspect = false;
            if(o instanceof ExtendedModelMap) doInspect = false;
            if(doInspect) {
                if(o instanceof BaseForm ) {
                    // only show form objects
                    AuditRecord ar = new AuditRecord();
                    ar.setUsername(principal.getUsername());
                    ar.setClazz(o.getClass().getCanonicalName());
                    ar.setMethod(methodName);
                    ar.setAsString(o.toString());
                    ar.setAudit_timestamp(timestamp);
                    auditRecordDAO.save(ar);
                }
            }
        }
    }
}

}
于 2012-05-20T15:25:33.107 に答える
2

actionComment注釈付きメソッドへのandactedUponIdから引数を取得しようとしている場合(両方とも文字列であると仮定)、次の@Aroundようにポイントカットにバインド条件を追加できます。

@Around("@annotation(ActivityLog) && args(actionComment,actedUponId)")
public Object logActivity(ProceedingJoinPoint pjp,
        String actionComment, String actedUponId) throws Throwable {
    // ... get other values from context, etc. ...
    // ... write to log ...
    pjp.proceed();
}

ポイントカットのargsバインディングは、関心のない他の引数がある場合に部分指定モードで使用できます。また、アスペクト自体が Bean であるため、アスペクトで行われている他のすべてのものに配線できます。通常の方法。

同じメソッド呼び出しで宣言型トランザクション管理を混在させる場合は、アスペクトの順序を正しくする必要があることに注意してください。これは、アスペクト Bean にも Spring インターフェースを実装させ、to 属性をOrdered介してトランザクションの優先順位を制御することによって部分的に行われます。(それが不可能な場合は、直接トランザクション処理を使用して巧妙なことを行う必要があります。これは、正しく行うための非常に苦痛なオプションです...)order<tx:annotation-driven/>

于 2012-05-20T16:04:01.350 に答える
0

アドバイスでへの参照をorg.aspectj.lang.JoinPoint取得します。で実行されているターゲットメソッドの名前を取得できます。エントリをtoShortString()含むループアップ/プロパティファイルを作成method-name=commentsできます。このコメントは、POJO.actionComment.method-nameに入力できます。に設定されPOJO.actedUponIdます。

データアクセスメソッドがアドバイスされ、サービスメソッドが@Transactionalを使用する場合、アドバイスが同じトランザクション内で実行されることを願っています。

于 2012-05-18T09:46:15.190 に答える