例如这个类: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)