例如這個類: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)