使用mybatis-spring以后,使用的就是mapper接口,能够直接当传统的DAO来使用,若是在mapper之上又包一层dao的话,则会使开发变得繁琐,改了mapper的xml以后,又得改mapper接口,以后还得改dao,再改service,很是不便利。html
要去使用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 { ... } }
使用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*(..)) && !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" /> <aop:pointcut id="datalogUpdatePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..update*(..)) && !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" /> <aop:pointcut id="datalogDeletePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..delete*(..)) && !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
一、若是service层有实现接口(好比下载组件的接口),则在其余地方注入的时候必须使用接口声明,不然会报错spa
二、拦截mapper,若是使用注解@Aspect ,必须强制使用JDK代理。.net
Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象建立代理。(建议尽可能使用JDK的动态代理)若是被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。全部该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则建立一个CGLIB代理。http://www.cnblogs.com/hustyangli/archive/2008/09/01/1281319.html