Bootstrap

分布式补充知识 02.AOP的重要注解@annotation ,使用添加缓存和清空缓存

01.在项目中创建一个包annotation包:
在这里插入图片描述
在创建新的java.class文件时候,选择annotation在这里插入图片描述
写一个自定义的注解,名字叫做RequiredCache

package com.cy.annotation;

package com.cy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//表示注解作用范围是运行时
@Target(ElementType.METHOD)//注解修饰类型是方法
public @interface RequiredCache {
 
}

再写切面类(用来实现这个注解):

package com.cy.Aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Aspect
@Component
public class sysCacheAspect {
    //实现在有自定义注解的方法中添加缓存
    //1.声明一个缓存变量,通常使用map来做缓存
    private Map<Object,Object> cache=new ConcurrentHashMap<>();

    //2.切入点
    @Pointcut("@annotation(com.cy.annotation.RequiredCache)")
    public void docache(){}
    //3.通知
    @Around("docache()")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        //先从缓存中获取对象
        System.out.println("从缓存中获取数据");
        Object result= cache.get("datakey");
        //如果缓存中没有的话,执行目标方法在数据库中去查找数据
        if(result!=null) return result;
        result= jp.proceed();
        //把数据放入缓存中
        System.out.println("将数据放入到缓存中");
        cache.put("datakey",result);
        //返回结果

        return result;
}
}

在一个查找方法中,自己添加一个刚才写的自定义注解@RequiredCache

         @RequiredCache
         @Override
         public List<Map<String, Object>> findObjects() {
         List<Map<String,Object>> list= sysMenuDao.findObjects();
         if(list==null||list.size()==0)
         throw new serivceException("没有对应的菜单信息");
         return list;
        }

清空缓存,在显示数据的时候需要及时(比如修改新增之后的查询界面数据还是从缓存中读取的,不及时更新),而缓存中的内容使用map集合的时候,没有去写更新的操作,所以,可以再去声明一个自定义的注解用来清空缓存。
自定义注解RequiredClear

package com.cy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredClear {
}

写切面类(用来实现这个注解):
还是上一个切面类,需要添加新的切入点@pointcut

 //2.切入点
    @Pointcut("@annotation(com.cy.annotation.RequiredCache)")
    public void docache(){}//添加缓存的切入点
    @Pointcut("@annotation(com.cy.annotation.RequiredClear)")
    public void docacheclear(){}//添加清空缓存的切入点

写通知:
上次的是环绕通知,这个是返回通知

@AfterReturning("docacheclear()")
    public  void doafterreturning(){
          cache.clear();
}

在查找方法中添加自定义注解@RequiredClear

         @RequiredClear
         @RequiredCache
         @Override
         public List<Map<String, Object>> findObjects() {
         List<Map<String,Object>> list= sysMenuDao.findObjects();
         if(list==null||list.size()==0)
         throw new serivceException("没有对应的菜单信息");
         return list;
        }

多个切面类同时作用的时候优先级是用注解@order来完成的,数值越小优先级越高。
在这里插入图片描述

;