攔截Mybatis的mapper

1、背景

    使用mybatis-spring以後,使用的就是mapper接口,能夠直接當傳統的DAO來使用,若是在mapper之上又包一層dao的話,則會使開發變得繁瑣,改了mapper的xml以後,又得改mapper接口,以後還得改dao,再改service,很是不便利。html

 

2、攔截mapper的兩種配置

一、使用@Aspect註解

     要去使用jdk的代理,不然代理不了mapper(即mybatis代理的mapper沒有默認的構造器,cglib沒法再給這個代理構造代理,會報以下錯誤org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy13]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy13)java

<!-- 啓動對@Aspectj的支持 true爲cglib,false爲jdk代理,爲true的話,會致使攔截不了mybatis的mapper-->
    <aop:aspectj-autoproxy proxy-target-class="false" />

    以後就是使用註解去配置攔截,進行修改記錄的操做spring

@Aspect
@Component
public class DatalogAspect {
    private static final Logger logger = LoggerFactory.getLogger(DatalogAspect.class);
    @Resource
    private ActionMapper actionMapper;
    @Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.insert*(..)) && !execution(public * com.yami.infrastructure.repository.mapper.ActionMapper.insert*(..))")
    public void insert(){
    }
    @Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.update*(..))")
    public void update(){
    }
    @Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.delete*(..))")
    public void delete(){
    }
    @Around("insert() || update() || delete()")
    public Object addOperateLog(ProceedingJoinPoint pjp) throws Throwable { 
        ...
    }
    }

二、使用MethodInterceptor

      使用aopalliance的MethodInterceptorexpress

(1)配置文件mybatis

        去掉對@Aspect註解的支持(也能夠不去掉,只要不是proxy-target-class = true就能夠)。而後配置aopapp

 <bean id="datalogInterceptor" class="com.yami.infrastructure.datalog.DatalogInterceptor" />
    <aop:config>
        <aop:pointcut id="datalogInsertPointCut" expression="execution(* com.yami.infrastructure.repository.mapper..insert*(..)) &amp;&amp; !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
        <aop:pointcut id="datalogUpdatePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..update*(..)) &amp;&amp; !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
        <aop:pointcut id="datalogDeletePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..delete*(..)) &amp;&amp; !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
        <aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogInsertPointCut" />
        <aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogUpdatePointCut" />
        <aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogDeletePointCut" />
    </aop:config>

(2)實現MethodInterceptoride

public class DatalogInterceptor implements MethodInterceptor{
    private static final Logger logger = LoggerFactory.getLogger(DatalogInterceptor.class);
    public DatalogInterceptor() {
    }
    @Resource
    private ActionMapper actionMapper;
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Method method = methodInvocation.getMethod();
        String methodName = method.getName();
        Class<?> cls = method.getDeclaringClass();
        Object service = methodInvocation.getThis();
        Object[] args = methodInvocation.getArguments();
        Integer actionType = -1; 
        ...
    }
}

  相比較而言,使用@Aspect註解會比較好用一點(用這個註解/methodInterceptor都攔截不了被同一個類的方法內部調用的方法)this

3、注意事項

    一、若是service層有實現接口(好比下載組件的接口),則在其餘地方注入的時候必須使用接口聲明,不然會報錯spa

    二、攔截mapper,若是使用註解@Aspect ,必須強制使用JDK代理。.net

      Spring AOP部分使用JDK動態代理或者CGLIB來爲目標對象建立代理。(建議儘可能使用JDK的動態代理)若是被代理的目標對象實現了至少一個接口,則會使用JDK動態代理。全部該目標類型實現的接口都將被代理。若該目標對象沒有實現任何接口,則建立一個CGLIB代理。http://www.cnblogs.com/hustyangli/archive/2008/09/01/1281319.html

相關文章
相關標籤/搜索