Spring使用注解实现AOP

Posted root_zhb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(..))")

以上是关于Spring使用注解实现AOP的主要内容,如果未能解决你的问题,请参考以下文章

使用Spring的注解方式实现AOP

使用Spring的注解方式实现AOP

Spring的注解方式实现AOP

实现自定义 Spring AOP 注解

实现自定义 Spring AOP 注解

spring学习5:基于注解实现spring的aop