AOP

AOP:

AOP=通知方法(写在切面中,@Aspect注解的类)+切入点表达式

通知方法

1.before通知 在执行目标方法之前执行
2.afterReturning通知 在目标方法执行之后执行
3.afterThrowing通知 在目标方法执行之后报错时执行
4.after通知 无论什么时候程序执行完成都要执行的通知

上述的4大通知类型,不能控制目标方法是否执行.一般用来记录程序的执行的状态.
一般应用与监控的操作.

5.around通知(功能最为强大的) 在目标方法执行前后执行.
因为环绕通知可以控制目标方法是否执行.控制程序的执行的轨迹.

切入点表达式

1.bean(“bean的ID”) 粒度: 粗粒度 按bean匹配 当前bean中的方法都会执行通知.
2.within(“包名.类名”) 粒度: 粗粒度 可以匹配多个类
3.execution(“返回值类型 包名.类名.方法名(参数列表)”) 粒度: 细粒度 方法参数级别
4.@annotation(“包名.类名”) 粒度:细粒度 按照注解匹配

JoinPoint 对象常用API

方法名功能
point.getSignature()封装了被注解所修饰的方法所在类的信息,得到的是方法签名(方法名和参数类型)
point.getTarget()封装了被注解所修饰的方法的信息
point.getArgs()封装了被注解所修饰的方法的参数信息
point.getSignature().getName()被修饰的方法的方法名
point.getSignature().getMethod()封装了被修饰的方法的信息
package com.jt.aop;

import com.jt.annotation.CacheFind;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
@Slf4j
@Aspect     
@Component
public class CacheAop {
@Around("@annotation(com.jt.annotation.CacheFind)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //目标对象的Class类型
        Class targetClass=joinPoint.getTarget().getClass();
        System.out.println("joinPoint.getTarget()-->"+joinPoint.getTarget());
        System.out.println("targetClass-->"+targetClass);
        //目标对象的方法名
        String methodName=joinPoint.getSignature().getName();
        System.out.println("joinPoint.getSignature()-->"+joinPoint.getSignature());
        System.out.println("methodName-->"+methodName);
        //获取参数类型
        Object[] argsObj=joinPoint.getArgs();
        System.out.println("argsObj-->"+argsObj);
        System.out.println("argsObj-->"+Arrays.toString(argsObj));
        Class[]argsClass=null;
        //对象转化为class类型
        if(argsObj.length>0){
            argsClass=new Class[argsObj.length];
            for(int i=0;i<argsObj.length;i++){
                argsClass[i]=argsObj[i].getClass();
            }
        }
        //获取方法对象
        Method targetMethod=targetClass.getMethod(methodName,argsClass);
        System.out.println("targetMethod-->"+targetMethod);
        //获取方法上注解
        if(targetMethod.isAnnotationPresent(CacheFind.class)){
            CacheFind cacheFind=targetMethod.getAnnotation(CacheFind.class);
            String key=cacheFind.preKey()+"::"+Arrays.toString(joinPoint.getArgs());
            System.out.println("key-->"+key);
        }
        Object result=joinPoint.proceed();
        return result;
    }
}

输出结果

joinPoint.getTarget()-->com.jt.service.ItemCatServiceImpl@1030359b
targetClass-->class com.jt.service.ItemCatServiceImpl
joinPoint.getSignature()-->List com.jt.service.ItemCatServiceImpl.findItemCatList(Long)
methodName-->findItemCatList
argsObj-->[Ljava.lang.Object;@465014a7
argsObj-->[0]
targetMethod-->public java.util.List com.jt.service.ItemCatServiceImpl.findItemCatList(java.lang.Long)
key-->ITEMCAT_PARENTID::[0]
    @Around("@annotation(cacheFind)")
    /**
     * @Around("@annotation(cacheFind)"),里面虽然是"cacheFind",但是框架会自动搜索,
     * 搜索到下面的方法后,会找到大写的"CacheFind",路径是"com.jt.annotation.CacheFind"
     * 因此编译的时候,虽然写的是"@Around("@annotation(cacheFind)")",但是实际编译的还是
     * "@Around("@annotation(com.jt.annotation.CacheFind)")"
     */
    public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind) throws Throwable {
        String preKey=cacheFind.preKey();
        String key=preKey+"::"+Arrays.toString(joinPoint.getArgs());
        Object result=null;
        if (jedis.exists(key)){
            String json=jedis.get(key);
            //获取方法对象
            //MethodSignature 是getSignature的子类
            MethodSignature methodSignature=(MethodSignature) joinPoint.getSignature();
            //获取方法返回值类型
            Class returnType=methodSignature.getReturnType();
            result=ObjectMapperUtil.toObj(json,returnType);
        }else{
            result=joinPoint.proceed();
            String json= ObjectMapperUtil.toJson(result);
            if(cacheFind.seconds()>0){
                jedis.setex(key, cacheFind.seconds(), json);
            }else{
                jedis.set(key, json);
            }
        }
        return result;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值