Spring-AOP

概念
AOP (Aspect Oriented Programming)是一种面向切面的编程的思想.

为什么用使用AOP
在写代码的过程中,如果把业务的核心代码和其他的一些代码堆放在一起,会造成代码的耦合度很高,不利于为维护,而导致牵一发动全身.如果使用面向对象OOP的思想,把每个业务逻辑中的公共方法都抽取出来作为一个公共类公共方法,需要就调用,但仍然还是需要去引用这个类然后去调用这个方法.为了解决重复代码,维护麻烦的问题,使用AOP动态的,不影响原先代码前提下执行的.

什么是切面(Aspect)
切面是是通知和切点的结合,一个切面就可以规定了在什么时候什么位置做什么事,例如在核心程序类执行前调用某个切面的通知

什么是切点(Pointcut)
切点存在于切面里面,我们需要定义这个不同的切点在哪些连接点上执行通知,如果说通知规定了切面是在什么时候,干了什么事的话,那么切点就是规定在哪个位置下去去切入这个切面

什么是通知
在AOP中,通知分为以下几种通知

  • 前置通知,Begore
  • 后置通知,After(在目标方法完成之后调用通知,此时不会关心方法的输出是什么)
  • 返回通知,After-returning(在目标方法成功执行之后调用通知)
  • 异常通知,After-throwing(抛出异常的通知)
  • 环绕通知,Around,这是个很强大的通知,使用try…catch能够代替前面四种通知

什么是连接点
连接点是在应用执行过程中能够插入切面的一个点,简单来说就是调用切点的那个方法.一般连接点就是核心业务.

切入点表达式:通常在项目中的用法execution(* *..*Service.*(..))
可以按照顺序读一下
execution是必须的
public修饰符可以省略,execution(public * *..*Service.*(..))
修饰符省略的情况下返回值不能省略execution(*int *..*Service.*(..))这种就是错误的
*… 表示多重包下
*Service 表示Service结尾的类名
*表示所有方法
(…)表示所参数列表任意

切入点表达式的使用
一般使用统一管理切入点的方式
引入切入点
统一的管理切入点的类

参考代码

@Aspect
@Component
@Order(3)
public class LogAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(* *..*Service.*(..))")
    public void pointCutDecoration(){
    }
    @Before("com.ycy.aop.aspect.PointCut.pointCutDecoration()")
    public void printLogBeforeCoreOperation(JoinPoint joinPoint){
        //通过spring传入的JoinPoint对象获取方法名,方法实参,返回值,异常信息
        String targetMethodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        //把数组转成集合方便打印,调用Arrays的静态方法
        List<Object> argumentList = Arrays.asList(args);
        logger.debug("[AOP前置通知--------]"+"[目标方法:]"+targetMethodName+"[方法实参:]"+argumentList);
    }
    @AfterReturning(value = "com.ycy.aop.aspect.PointCut.pointCutDecoration()",returning ="returnValue" )
    public void printLogAfterCoreOperation(JoinPoint joinPoint,Object returnValue){
        logger.debug("[AOP返回通知--------]"+"[返回值:]"+returnValue);
    }

    @AfterThrowing(value = "com.ycy.aop.aspect.PointCut.pointCutDecoration()",throwing = "throwable")
    public void printLogAfterCoreOperationFailed(JoinPoint joinPoint,Throwable throwable){
        //从传入的throwable对象的原因
        Throwable cause = throwable.getCause();
        //循环查找原因,直到cause为null
        while (cause!=null){
            throwable =cause;
            //如果这个cause为null了,那么异常信息就停留在throwable了
            cause = throwable.getCause();
        }
        String throwableName = throwable.getClass().getName();
        String message = throwable.getMessage();
        String s = throwable.toString();
        logger.debug("[AOP异常通知--------]"+"[异常类型:]"+throwableName+"[异常信息是:]"+message);
        logger.debug("[AOP异常通知--------]"+"[异常信息是:]"+s);
    }
    @After("com.ycy.aop.aspect.PointCut.pointCutDecoration()")
    public void printLogAfterCoreOperationFinished(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        logger.debug("[AOP后置通知--------]"+"[目标方法;]"+name);
    }
}

打印结果
打印结果

@Order注解的使用
在开发过程中,可能会有多个切面的存在,我们需要规定切面的优先级
@Order(较小的数):优先级高
@Order(较大的数):优先级低
经典的应用场景就是缓存切面和事务切面,如果事务的切面优先于缓存的切面的话,会让所有的请求都去开启事务查询数据库,频繁操作数据库这是非常不合理的,所以应该把缓存切面的优先级高于事务切面,一旦有请求进来,应该先查询缓存,一旦缓存有数据就直接返回,不去查询数据库,如果缓存没有该数据才进数据库,并且查到后也应该再把数据置于缓存.


先到这

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值