Spring使用注解实现AOP

1、AOP术语

  1. target:目标类,需要被代理的类。
  2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
  3. PointCut 切入点:已经被增强的连接点。例如:某个增强的方法
  4. advice 通知/增强:增强代码。例如:after、before
  5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程。
  6. proxy 代理类
  7. Aspect(切面):是切入点pointcut和通知advice的结合
    一个线是一个特殊的面。
    一个切入点和一个通知,组成成一个特殊的面。

2、AspectJ 通知类型

  1. @Before:前置通知(应用:各种校验)
    在方法执行前执行,如果通知抛出异常,阻止方法运行

  2. @AfterReturning:后置通知(应用:常规数据处理)
    方法正常返回后执行,如果方法中抛出异常,通知无法执行
    必须在方法执行后才执行,所以可以获得方法的返回值。

  3. @Around:环绕通知(应用:十分强大,可以做任何事情)
    方法执行前后分别执行,可以阻止方法的执行
    必须手动执行目标方法

  4. @AfterThrowing:抛出异常通知(应用:包装异常信息)
    方法抛出异常后执行,如果方法没有抛出异常,无法执行

  5. @After:最终通知(应用:清理现场)
    方法执行完毕后执行,无论方法中是否出现异常

3、代码示例

存在一个service实现类,作用是插入数据,代码如下:

package com.zhb.service.impl;

import com.zhb.dao.PaymentDao;
import com.zhb.entity.Payment;
import org.springframework.stereotype.Service;
import com.zhb.service.PaymentService;

import javax.annotation.Resource;

@Service
public class PaymentServiceImpl implements PaymentService
{
    @Resource
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment)
    {
        return paymentDao.create(payment);
    }
}

3.1、@AfterReturning后置通知

@Aspect注解将PaymentAspect 声明为一个切面
@AfterReturning注解中通过returning属性指定参数的名称,用于接受目标方法的返回值。

@Aspect
@Component
public class PaymentAspect {
    private static final Logger logger = LoggerFactory.getLogger(PaymentAspect.class);

    @AfterReturning(
            returning = "result",
            pointcut = "execution(* com.zhb.service.impl.PaymentServiceImpl.create(..))"
    )
    @SuppressWarnings({"unchecked"})
    public Object userInsert(JoinPoint joinPoint, Object result) {
    	//将参数转为List
    	//List<Object> args = Arrays.asList(joinPoint.getArgs());
        Object[] args = joinPoint.getArgs();
        Payment payment = null;
        for (Object arg : args) {
            if (arg instanceof Payment) {
                payment = (Payment) arg;
            }
        }
        logger.info("测试切面"+payment.getSerial());
        return result;
    }
}

3.2、@Around环绕通知

实现一个切面类,通过环绕通知记录方法调用详情(也可记录日志等)

package com.zhb.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class PaymentAspect {
    private static final Logger logger = LoggerFactory.getLogger(PaymentAspect.class);

    @Around(
            value = "execution(* com.zhb.service.impl.PaymentServiceImpl.create(..))"
    )
    @SuppressWarnings({"unchecked"})
    public Object userInsert(ProceedingJoinPoint joinPoint) {
        Object result=null;
        try {
            result= joinPoint.proceed();
            logger.info("调用" + joinPoint.getTarget() + "的" + joinPoint.getSignature().getName()
                    + "方法。方法返回值:" + result);

        } catch (Throwable e) {
            logger.error(joinPoint.getSignature().getName() + "方法发生异常:" + e);
        }finally {
            logger.info(joinPoint.getSignature().getName() + "方法结束执行。");
        }
        return result;
    }
}

注意:此处的方法返回值是Object,以及最终的return result;

4、其他问题

4.1、多个切入点

@AfterReturning(returning = "result",
        pointcut = "execution(* com.zhb.service.impl.PaymentServiceImpl.create1(..))" +
                "|| execution(* com.zhb.service.impl.PaymentServiceImpl.create2(..))")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值