Spring AOP類中方法調用自身其餘方法的解決方案

由來

例如這個類:spring

@Repository
public class ErpRemarkRecordDao extends BaseDao<ErpRemarkRecord> {

    @Override
    protected String getTableName() {
        return "erp_remark_record";
    }

    /** 得到最新溝通記錄 */
    @JpaQuery
    public String findRemarkBySourceIdAndSourceTypeSortByIdDesc(Long sourceId, int sourceType) {
        return null;
    }

    /** 得到線索的最新備註 */
    public String findNewestRemarkByClueId(Long id) {
        return findRemarkBySourceIdAndSourceTypeSortByIdDesc(id, 1);
    }
}

findNewestRemarkByClueId()方法須要調用類中的findRemarkBySourceIdAndSourceTypeSortByIdDesc()方法,問題是findRemarkBySourceIdAndSourceTypeSortByIdDesc()進行了AOP攔截,findNewestRemarkByClueId()在類中直接調用findRemarkBySourceIdAndSourceTypeSortByIdDesc()方法,將不會通過AOP攔截ide

工具類

寫了一個工具類來解決本身調用本身的問題:工具

/** spring aop的輔助工具類 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Aops {
    /**
     * 爲了解決循環aop調用,要使用這個方法。另:spring默認的代理必須爲cglib,且exposeProxy=true <br>
     * 用法:
     * 
     * <pre>
     * Aops.getSelf(this)
     * </pre>
     * 
     * @param t
     *            t通常入參爲this,而this只能是類對象,不多是代理類,這一點要注意
     */
    @SuppressWarnings("unchecked")
    public static <T> T getSelf(T t) {
        try {
            T curT = (T) AopContext.currentProxy();
            if (curT.getClass().getSuperclass().equals(t.getClass())) { // 有時出現currentProxy和t類型不一致,這裏作一下判斷
                return curT;
            }
        } catch (IllegalStateException e) {
            // 通常會報錯:Cannot find current proxy: Set 'exposeProxy' property on
            // Advised to 'true' to make it available.
            // 此時代表這個類中沒有aop方法,直接返回t便可
        }
        return t;
    }
}

上面的代碼這樣改:this

@Repository
public class ErpRemarkRecordDao extends BaseDao<ErpRemarkRecord> {

    @Override
    protected String getTableName() {
        return "erp_remark_record";
    }

    /** 得到最新溝通記錄 */
    @JpaQuery
    public String findRemarkBySourceIdAndSourceTypeSortByIdDesc(Long sourceId, int sourceType) {
        return null;
    }

    /** 得到線索的最新備註 */
    public String findNewestRemarkByClueId(Long id) {
        return Aops.getSelf(this).findRemarkBySourceIdAndSourceTypeSortByIdDesc(id, 1);
    }
}

Aops.getSelf(this)得到代理對象,而非當前對象。代理

須要注意的是,Spring容器中AOP的配置必須爲cglib代理(不能用Java Proxy),且exposeProxy=true。
若是用的是Spring Boot,須要在啓動類加上註解:code

@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
相關文章
相關標籤/搜索