直接上代码:
@Component public class LogErrorAspect { private static final Logger LOGGER = LoggerFactory.getLogger(LogErrorAspect.class); private static final String NB = "nb"; @Pointcut(value = "within(com.aop.service.order..*) && @annotation(com.aop.intf.dto.order.EasyValid)") public void logErrorPointCut(){ } /*异常拦截加参数e
@AfterThrowing(value="within(com.aop.ysma..*)", throwing="e")
可行方案:能拦截到service层代码,但是如此书写却是拦截不到controller的
@Around("within(com.aop.service.order..*) && @annotation(easyValid)") 可行方案:能拦截到service和controller层代码 两个参数 @Around(value = "execution(@com.aop.service.order * *(..)) && @annotation(easyValid)") 可行方案:能拦截到service和controller层代码 @Around("within(com.ysma.aop..*) && @annotation(com.ysma.aop.intf.base.db.ReadOnly)") 可行方案@Around("@annotation(com.aop.service.order.EasyValid)")
public Object aroundSimple(ProceedingJoinPoint pj, EasyValid easyValid) throws Throwable { LOGGER.debug("diy aroundSimple ================="); return pj.proceed(); }*/ /**不可行方案 @Around(value = "logErrorPointCut() && args(com.aop.intf.dto.order.EasyValid)", argNames = "pj, easyValid") */ @Around(value = "logErrorPointCut() && args(easyValid)", argNames = "pj, easyValid") public Object around(ProceedingJoinPoint pj, EasyValid easyValid) throws Throwable { /*@Around("logErrorPointCut()") public Object around(ProceedingJoinPoint pj) throws Throwable {*/ //pj.getClass().getAnnotation(EasyValid.class); LOGGER.debug("diy operation ================="); if(easyValid == null){ LOGGER.debug("easyValid is null ================="); return pj.proceed(); } boolean nb = NB.equals(easyValid.source()); return pj.proceed(); } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EasyValid { /** * b/g 必须输入 * @return */ String source(); /** * 入参 必须输入 * @return */ String operatiton() default ""; }注:被注解的方法须是public方法 protect和private方法虽不会报错却也不会生效
那么问题来了:采用不可行方案将pointcut和advice拆分开来我的切面就拦截不到标记了annotation的服务; 采用可行方案将pointcut和advice不拆分,就能正常获取参数并拦截标记了annotation的服务; 备注:1、我跟踪了一下spring的源码,发现采用不可行的方案时,spring只会取其中的easyValid参数并匹配并且成功匹配到了也能将对应的标记了@EasyValid的服务作为cancaditate加入候选者列表等待匹配调用。 但是临门一脚的时候就跳过了我的LogErrorAspect切面了。 2、我将pj做为参数放入到args里面也会报错。说没有匹配类型的参数。是因为ProceedingJoinPoint是JoinPoint的子类的缘故么?貌似这么理解也不太科学 猜想:是不是代理类proxy在invocation的时候发现参数数目不匹配跳过了不可行方案的方法? 3、之前有看过文章说 controller并不在spring管理范围内,service在spring管理范围内。 所以service走spring代理,aop切面都能切中,但是controller就切不中 此处提供了另类的方式切中controller的aop方式 求教:pointcut和advice拆分的情况下如何定义除pj以外的参数