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来完成的,数值越小优先级越高。