2012-05-18 42 views
3

我已經經歷了一些春/ AOP教程和有所熟悉自己與相關概念的最佳方式。春/ AOP:實現一個活動登錄數據庫

現在我已經達到了我的要求,我需要創建一個活動日誌實現,它將保存登錄用戶在數據庫中的活動,其範圍可以從申請服務或創建新用戶以防Admin用戶,等在具有註釋的任何方法的調用(比如@ActivityLog),此信息是在actorId形式,actionCommentactionTimeactedUponId要永久保存,...等等。現在

,如果我創建一個POJO類(映射到數據庫中的ActivityLog表),並且想要從Advice中保存此數據(最好使用與方法,方法相同的事務使用@Transactional註釋),我如何實際填充此POJO中的變量?我大概可以從會話對象& actionTime可以簡單地new Date()actorId但有關actionComment/actedUponId動態值怎麼樣?

任何幫助將是輝煌! (順便說一句,我有一個要求,不使用Hibernate的攔截器。)

回答

0

你會得到在你advice.You的org.aspectj.lang.JoinPoint參考可以得到目標方法的名稱與正在執行toShortString()。你可以有一個環 -/​​條目。此註釋可填入POJO.actionComment.method-name可設置爲POJO.actedUponId

我希望這些建議應在同一事務中運行,如果該數據訪問方法是諫和服務方法使用@Transactional。

+0

感謝您的答覆。有趣的方法,但actionComment可能來自用戶輸入!也想補充一點,我猜我應該使用After Advice(儘管不知道它是否會使用與原始方法相同的事務)!謝謝,Sumit – Sumit

+0

BTW actedUponId應該是用戶的userId操作(添加,刪除等)正在由管理員執行。 – Sumit

+0

如果使用spring-security,principal/user必須可用'SecurityContextHolder..getUserPrincipal()'。你打算如何獲取userId? –

2

下面是一個完整的例子:

@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); 
       } 
      } 
     } 
    } 
} 

} 
2

如果你正在尋找擺脫參數註釋方法actionCommentactedUponId(假設他們都是字符串),你可以結合字詞添加到您@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的切入點結合可以在部分指定的模式下使用,萬一有關於其他的參數,你是不感興趣的,並且正弦e這個方面本身就是一個bean,它可以以正常的方式連接到其他所有的事物上。

需要注意的是,如果你在同一個方法調用混合聲明式事務管理,你一定要得到正確的方面的順序。部分原因是通過使aspect bean實現Spring Ordered接口,並通過order屬性控制事務的優先級爲<tx:annotation-driven/>。 (如果那是不可能的,你將被迫做聰明的事情,直接交易處理;這是一個大大更痛苦的選項來獲得正確的...)