Spring AOP的一個使用例子

0.前言

    學習Spring,確定會瞭解IOC和AOP的思想,除了Spring的基本使用,本身在實際應用中,還真沒特地使用過AOP的功能。最近有一個項目使用到了Spring,因爲以前也沒有Spring的實際工做經驗,加上項目比較着急,因此有不少細節不完善的地方。下面介紹AOP使用的一個例子,有不對或者更好的解決方法,歡迎指正。 java

1.功能需求

    項目是一個學習小組,用戶能夠建立小組,加入小組,離開小組,以及其它一系列功能。在小組首頁裏有一個小組動態。這就須要咱們在程序中,處理用戶基本操做之外,還要保存相應的小組動態。 服務器

2.基本實現

    首先想到的就是寫一個公共的方法,在須要的地方進行調用。由於裏面有兩個DAO操做,因此封裝成了一個service方法。在不一樣的service中注入service調用這個方法。這個方法大概須要幾個參數,記錄小組id,用戶id,以及動態的type 學習

public void addTeamNewsLog(long team_id,long user_id,int type){
        long ref = studyTeamInfoDAO.getSeqAllRef();
        StudyTeamNews news =new StudyTeamNews();
        news.setRef(new BigDecimal(ref));
        news.setTeamId(new BigDecimal(team_id));
        news.setUserId(new BigDecimal(user_id));
        news.setType((short) type);
        studyTeamNewsDAO.insertSelective(news);
    }

好比 測試

1.建立小組 (首先建立小組, 而後小組建立動態 , 最後添加關聯) spa

2.記錄用戶和小組關聯(先添加關聯,再記錄用戶加入動態,刪除用戶申請消息) .net


    相似這樣的狀況,程序中大概還有幾個地方。 debug

3.功能改進

    今天項目上線了,功能一切正常,下午在看代碼的時候,忽然想到Spring有AOP的功能,我能夠考慮一下AOP去實現這個功能。 日誌

    @黃勇 博客的 《AOP那些事兒》http://my.oschina.net/huangyong/blog/161402 code

    找到了Spring AOP的功能實現  12. Spring + AspectJ(基於註解:經過 AspectJ execution 表達式攔截方法) xml

    在Spring的配置文件中加入

<aop:aspectj-autoproxy proxy-target-class="true"/>

   在項目下新建一個package,建立了一個Aspect類,加入一個新方法

    1.首先經過AspectJ execution表達式 寫攔截的方法 (Intellij IDEA有智能提示)

    2.在after()方法打一個斷點 

@Around("execution(* com.etiantian.studyteam.dao.StudyTeamInfoDAO.insert(..))")
    public Object addTeamOk(ProceedingJoinPoint pjp)throws  Throwable{
        Object result = pjp.proceed();
        after();
        return result;
    }

    重啓服務器....建立戰隊....OK,進入斷點了,說明咱們的AOP功能起做用了,下面我就能夠記錄動態了

    3.在pjp.proceed();方法打一個斷點,而後debug進去 看看pjp中有什麼東西,發現有方法名,有參數,再上網查一下ProceedingJoinPoint這個類,能夠經過getArgs 得到切入方法的參數。

    4.根據本身的功能須要,修改方法

@Around("execution(* com.etiantian.studyteam.service.facede.StudyTeamJUserService.saveStudyTeamJUser(..))")
    public Object addTeamUser(ProceedingJoinPoint pjp)throws Throwable {
        long team_id=Long.parseLong(pjp.getArgs()[0].toString());
        long user_id=Long.parseLong(pjp.getArgs()[1].toString());
        Object result = pjp.proceed();
        addStudyTeamLog(team_id, user_id, StudyTeamBaseAction.ADD_TEAM_USER);
        return result;
    }

    @Around("execution(* com.etiantian.studyteam.dao.StudyTeamInfoDAO.insert(..))")
    public Object addTeamOk(ProceedingJoinPoint pjp)throws  Throwable{
        Object result = pjp.proceed();
        StudyTeamInfo st =(StudyTeamInfo)pjp.getArgs()[0];
        addStudyTeamLog(st.getTeamId().longValue(), st.getcUserId().longValue(), StudyTeamBaseAction.ADD_TEAM_OK);
        return result;
    }

    private void addStudyTeamLog(long team_id,long user_id,int type){
        studyTeamInfoService.addTeamNewsLog(team_id,user_id,type);
    }

   5.註釋掉原有service中的全部 addTeamNewsLog方法調用,測試一切正常... 

4.總結

    本身在項目中,也是先實現基本功能的增刪改查,而後再不斷完善功能,好比小組動態就是後來加入的,固然須要修改原來的程序。

    若是咱們使用AOP的方法,那麼原有程序咱們就能夠不用修改了,只用找到切入點,根據須要在切入點的先後加上相應的操做。並且維護起來也比較容易,好比咱們想去掉某個類型的日誌記錄,或者加入新的動態記錄,都不用再去修改源代碼。

   固然能夠參考@黃勇 博客的 《AOP那些事兒》http://my.oschina.net/huangyong/blog/161402,採用第十三種,經過自定義註解的方式進行實現,這樣就不用寫多個方法了....

  注:使用Spring+Aspectj 的AOP可能須要Cglib 的jar   

相關文章
相關標籤/搜索