• Spring Aop的简单记录


    1、Aop:面向切面编程

    项目可以粗略划分为两个模块:核心业务、周边功能。所谓切面,就是将周边功能抽离出来,做相应的处理的一种定义。

    切面可以带来的好处是,减少了重复的代码,将核心业务与周边功能解耦。

    2、Aop的一些定义

    • 连接点:程序执行的具体操作,例如:执行一个方法
    • 切入点(Pointcut):在哪些类,哪些方法上切入,一般是一组连接点匹配表达式
    • 通知(Advice):在方法执行的时间段(around、before、after、exception、return)做一些增强的功能
    • 切面(Aspect):切面 = 切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强!
    • 织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)
    • Aop代理(aop proxy) : aop框架创建的对象,有两种jdk动态代理、CGLIB代理。

    3、Aop织入的时期

    编译期:切面在目标类编译时织入,AspectJ就是这种方式
    类加载期:切面在目标类加载到JVM时织入
    运行期:切面在程序运行的某个时期被织入,一般在切面织入时:AOP容器会对目标对象动态创建一个代理对象。Spring Aop就是采用这种织入方式。

    4、Aop的一些注解

    @Ascept,定义切面类
    @Pointcut("execution(* com.example.springboot.controller.UserController.getVerify(..))"),标注切面的点
    Advice的几个分类:
    @Before 前置通知,在连接点方法前调用
    @Around 环绕通知,它将覆盖原有方法,但是允许你通过反射调用原有方法,
    @After 后置通知,在连接点方法后调用
    @AfterReturning 返回通知,在连接点方法执行并正常返回后调用,要求连接点方法在执行过程中没有发生异常
    @AfterThrowing 异常通知,当连接点方法异常时调用

    5、Aop+注解+Redis实现Controller层简单的缓存读取

    缺陷的地方:缓存数据与db一致性、缓存读取数据类型转换出错、缓存键id问题

    定义注解:

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CacheTarget {
    
        /**
         * 默认键
         * @return
         */
        String key() default "-1";
    
        /**
         * 转换的对象类型
         * @return
         */
        Class type() default Object.class;
    }
    

    定义Aop:

    @Slf4j
    @Component
    @Aspect
    public class CacheAop {
    
        @Autowired
        private RedisUtil redisUtil;
    
        @Pointcut("@annotation(com.example.springboot.annotation.CacheTarget)")
        public void point(){}
    
        @Around(value = "point()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("==around==");
    
            //得到其方法签名
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    
            CacheTarget cacheTarget = methodSignature.getMethod().getAnnotation(CacheTarget.class);
    
            String key = cacheTarget.key();
    
            //后续可以做缓存中数据类型相关操作
            Class type = cacheTarget.type();
    
            //参数名
            String[] parameterNames = methodSignature.getParameterNames();
            //参数值
            Object[] args = joinPoint.getArgs();
    
            //获取id的值
            int index = ArrayUtils.indexOf(parameterNames,"id");
            int id = (int)args[index];
    
            Object cacheValue = redisUtil.get(key + id);
            if(cacheValue != null){
                return cacheValue;
            }
    
            System.out.println("执行proceed");
            //执行方法
            Object result = joinPoint.proceed(args);
    
            return result;
        }
    
    }
    

    方法上使用该注解:

        /**
         * 根据id获取用户 + 缓存处理
         * @param id
         * @return
         */
        @CacheTarget(key = "user:", type = User.class)
        @GetMapping(value = "/redis/{id}")
        public User getUser(@PathVariable int id){
            log.info("执行mapper查询db");
            User user = userMapper.selectById(id);
            String cacheKey = USER_KEY + id;
            redisUtil.setEx(cacheKey,user,100);
            return user;
        }
    
    关于学习到的一些记录与知识总结
  • 相关阅读:
    Qt之悬浮球菜单
    electron中使用win.hide()再使用win.show()会引起窗口闪烁问题
    centos开放防火墙
    centos 设置CDN
    drfsave()更新操作
    os库获取/设置/删除环境变量
    def待学习的功能
    shell命令操作(jenkins执行后判断shell执行的对与错)
    使用templates模版
    centos安装vue前端环境
  • 原文地址:https://www.cnblogs.com/Zxq-zn/p/14320150.html
Copyright © 2020-2023  润新知