基于注解Spring AOP

发布于 2019-06-21  2556 次阅读


项目中使用到了工作流,每次走流程都会涉及到更新项目相关信息,同时去执行工作流,记录相应的日志信息,所以就考虑尽可能将业务操作和工作流相应的操作,日志剥离开来。

使用了如下注解:

@Aspect //启用aop
@Component //将当前类注册为bean

@Pointcut 切点

定义一个方法,用于声明切点表达式,该方法一般没有方法体,Pointcut用来申明切点表达式,通知直接使用定义的方法名即可引入当前的切点表达式。

Pointcut可使用 & || !等运算符。

@Pointcut("execution(public * com.sgkj.guarantee.controller.GuarTraditionController.processTradition(..))")
public void processTradition() {
}

这里写图片描述
切点表达式说明

@Before

前置通知,用于在切点表达式对应的方法之前执行的方法。

@After

后置通知,用于在切点表达式对应的方法之后执行的方法。

@AfterReturning

返回通知,用于 @After 之后,返回数据之前执行。

@Around

环绕通知,用于切点表达式方法前后的方法。

代码片段:

@Aspect
@Component
public class WorkFlowAspect {

    private Logger logger = Logger.getLogger("WorkFlowAspect");


    @Pointcut("execution(public * com.sgkj.guarantee.controller.GuarTraditionController.processTradition(..))||execution(public * com.sgkj.guarantee.controller.GuarSupplyCompanyController.processSupplyCompany(..))")
    public void processBusiness() {
    }

	//切点方法之前执行
    @Before("processTradition()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        logger.info("切面,参数检查");
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));

        String method = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName();
        logger.info("aspect finishing");
        logger.info("calling " + method);

    }

    /**
     * 退回,后置通知
     *
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "flowBack()")
    public void doAfterReturning(Object ret) throws Throwable {
	//切点方法和@After执行之后执行的方法。
    }

    //所有项目拦截
    @Around("processBusiness()")
    @Transactional
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("before logging");
        ReturnMessage returnMessage = null;
        HttpServletRequest request = null;
		//获取切点function的参数信息
        Object[] args = joinPoint.getArgs();
		//调用切点方法之前执行,用于属性检查,及附件上传情况检查
        //遍历参数
        for (Object arg : args) {
            if (arg instanceof GuarTradition) {
                
            } else if (arg instanceof GuarBaoHouWoring) {
                
            } else if (arg instanceof GuarSupplyCompany) {
                
            } else if (arg instanceof HttpServletRequest) {
                request = (HttpServletRequest) arg;
            }
        }
            //调用原接口,执行相应的业务代码
            Object proceed = joinPoint.proceed();
			
			//执行切点方法后,调用日志模块,记录日志信息
			
        logger.info("returning logging");
        return returnMessage;
    }

}


个人博客,用于记录工作日常的问题。