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)
相关文章
相关标签/搜索