AOP实现业务

1. AOP说明

1.1 AOP作用

利用AOP可以实现对方法(功能)的扩展.实现代码的解耦.

1.2 切面组成要素

切面 = 切入点表达式 + 通知方法

1.2.1 切入点表达式

1).bean(bean的ID) 拦截bean的所有的方法 具体的某个类 粗粒度的.
2).within(包名.类名) 扫描某个包下的某个类 com.jt.* 粗粒度的.
3).execution(返回值类型 包名.类名.方法名(参数列表)) 细粒度的
4).@annotation(包名.注解名) 细粒度的

1.2.2 通知方法

说明: 通知相互之间没有顺序可言. 每个通知方法都完成特定的功能,切记AOP的通知方法与目标方法之间的顺序即可.
1).before 目标方法执行前
2).afterReturning 目标方法执行后
3).afterThrowing 目标方法执行抛出异常时执行.
4).after 不管什么情况,最后都要执行的.
上述四大通知类型,一般用来记录程序的运行状态的.(监控机制)

5).around 目标方法执行前后都要执行.
如果要对程序的运行轨迹产生影响,则首选around.

1.2.3 AOP入门案例
@Aspect     //标识我是一个切面
@Component  //将对象交给spring容器管理  cacheAOP
public class CacheAOP {

    //切面 = 切入点表达式 + 通知方法
    //表达式1: bean(itemCatServiceImpl)  ItemCatServiceImpl类
    //@Pointcut("bean(itemCatServiceImpl)")
    //@Pointcut("within(com.jt.service.*)")  // .* 一级包下的类   ..* 所有子孙后代的包和类
    
    @Pointcut("execution(* com.jt.service..*.*(..))")
        //返回值类型任意, com.jt.service包下的所有类的add方法参数类型任意类型
        //写参数类型时注意类型的大小写
    public void pointcut(){}
    /**
     *
     * joinPoint代表连接点对象,一般适用于前四大通知类型(除around之外的)
     *        客人                         路人
     */
    @Before("pointcut()")
    public void before(JoinPoint joinPoint){
        //1.获取目标对象
        Object target = joinPoint.getTarget();
        System.out.println(target);
        //2.获取目标对象的路径 包名.类名.方法名
        String className = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = joinPoint.getSignature().getName();
        System.out.println("目标方法的路径:"+(className+"."+methodName));
        //3.获取参数类型
        System.out.println(Arrays.toString(joinPoint.getArgs()));
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("环绕通知执行");
        Object data = null;
        try {
            data = joinPoint.proceed(); //执行目标方法
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return data;
    }

}

2 AOP实现redis缓存

2.1 业务需求

需要通过自定义注解的形式动态实现缓存操作.通过注解获取其中的key.超时时间.
在这里插入图片描述

2.2 自定义注解的用法

在这里插入图片描述

2.3 编辑CacheAOP

package com.jt.aop;

import com.jt.annotation.CacheFind;
import com.jt.pojo.ItemDesc;
import com.jt.util.ObjectMapperUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import sun.misc.Cache;

import java.util.Arrays;

@Aspect     //标识我是一个切面
@Component  //将对象交给spring容器管理  cacheAOP
public class CacheAOP {

    @Autowired
    private Jedis jedis;

    /**
     * 实现思路:
     *      1.动态获取key   用户自定义的前缀+用户的参数[0,xx]
     *      2.判断key是否存在
     *             存在: 直接从redis中获取数据 JSON, 需要将json转化为具体对象  按照返回值类型进行转化
     *             不存在: 执行目标方法.获得返回值数据. 将返回值结果转化为JSON格式. 之后保存到缓存中.
     * @param joinPoint
     * @return
     */
    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind) throws NoSuchMethodException {
        Object result = null;
        //1.获取key的前缀
        String key = cacheFind.key();
        //2.获取方法参数
        String argString = Arrays.toString(joinPoint.getArgs());
        key = key + "::" + argString;
        try {
             //3.判断缓存中是否有数据
            if(jedis.exists(key)){
                String json = jedis.get(key);
                //5.获取返回值类型
                MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
                result = ObjectMapperUtil.toObject(json,methodSignature.getReturnType());
                System.out.println("AOP查询redis缓存");
            }else{
                //表示缓存中没有数据,执行目标方法
                result = joinPoint.proceed();
                String json = ObjectMapperUtil.toJSON(result);
                //4.判断数据中是否有超时时间
                if(cacheFind.seconds()>0){
                    jedis.setex(key,cacheFind.seconds(),json);
                }else{
                    jedis.set(key,json);
                }
                System.out.println("AOP执行数据库调用!!!!!");
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw new RuntimeException(throwable);
        }
        return result;
    }
}

2.4 商品分类名称优化

优化商品分类名称的名称. 在业务层添加缓存注解.
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值