由来
例如这个类:
@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拦截
工具类
写了一个工具类来解决自己调用自己的问题:
/** 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;
}
}
上面的代码这样改:
@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,需要在启动类加上注解:
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)