AOP
连接点罕用API
ProceedingJoinPoint只能盘绕告诉应用(ProceedingJoinPoint控制目标办法的执行),如果当做参数来用,必须位于参数的第一位
private void saveSysLog(ProceedingJoinPoint point){
//1.获取指标类(就相当于晓得了是哪一个类)
Class<?> targetCls = point.getTarget().getClass();
MethodSignature ms= (MethodSignature) point.getSignature();
System.out.println("ms________________"+ms);
String methodName = ms.getName();//再获取办法名
//2.获取类里的办法(类里有很多办法 通过办法名和办法参数类型可能确定是哪一个办法)
Method targetMethod=targetCls.getMethod(methodName,ms.getParameterTypes());
//3.获取指标办法上的注解
RequiredLog requiredLog = targetMethod.getAnnotation(RequiredLog.class);
//4.获取注解上的值
if(requiredLog!=null){
operation=requiredLog.value();
}
String method=targetCls.getName()+"."+methodName;
Object[] paramsObj=point.getArgs();
//转一般串
//String params= Arrays.toString(paramsObj);
//将参数转换为字符串
String params=new ObjectMapper().writeValueAsString(paramsObj);
}
public void before(JoinPoint joinPoint){
//getSignature:获取是一个对象(外面蕴含办法的返回值 办法名 办法参数)
String methodName = joinPoint.getSignature().getName();
String typeName = joinPoint.getSignature().getDeclaringTypeName();
System.out.println("指标办法的门路:"+typeName+"."+methodName);
// getArgs:返回指标办法的参数
Object[] args = joinPoint.getArgs();
System.out.println("参数:"+ Arrays.toString(args));
Class<?> methodClass = joinPoint.getTarget().getClass();
System.out.println("指标对象类型:"+methodClass);
入门案例
@Aspect //我是一个aop的切面类
@Component//将类交给spring容器治理
public class CacheAOP {
//公式=切入点表达式 + 告诉办法
/*
*对于切入点表达式的应用阐明
* 粗粒度:
* 1.bean(bean的Id)一个类 bean的Id指的是交给spring容易治理的类的类名小写 ,
* 也能够bean(*ServiceImpl) 多个类
* 2.within(包名.类名) 一个类/*代替就是多个
*/
@Pointcut("bean(itemCatServiceImpl)")
public void pointCut(){
//定义切入点表达式 只为了占位
}
//定义前置告诉,与切入点表达式进行绑定,留神绑定的是办法
@Before("pointCut()")
//等同于@Before("bean(itemCatServiceImpl") 区别:pointCut()示意切入点表达式的援用
//实用于多个告诉同用状况
public void before(JoinPoint joinPoint){
//getSignature:获取是一个对象(外面蕴含办法的返回值 办法名 办法参数)
String methodName = joinPoint.getSignature().getName();
String typeName = joinPoint.getSignature().getDeclaringTypeName();
System.out.println("指标办法的门路:"+typeName+"."+methodName);
// getArgs:返回指标办法的参数
Object[] args = joinPoint.getArgs();
System.out.println("参数:"+ Arrays.toString(args));
Class<?> methodClass = joinPoint.getTarget().getClass();
System.out.println("指标对象类型:"+methodClass);
System.out.println("我是前置告诉");
}
@Around("pointCut()")
public Object doaround(ProceedingJoinPoint joinPoint) {
/**
* ProceedingJoinPoint只能盘绕告诉应用(ProceedingJoinPoint控制目标办法的执行),
* 如果当做参数来用,必须位于参数的第一位,
*/
Object result=null;
try {
result = joinPoint.proceed();//执行下一个告诉或指标办法
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("盘绕告诉完结");
return result;
}
}
AOP 实现 Redis缓存
编写配置类
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
return new Jedis(host,port);
}
}
编写工具类
public class ObjectMapperUtil {
private static final ObjectMapper mapper=new ObjectMapper();
//1.将用户传递的数据转化为json
public static String toJson(Object object){
if(object==null) {
throw new RuntimeException("传递的数据为null 请查看");
}
try {
String json = mapper.writeValueAsString(object);
return json ;
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//要求用户传递什么样的类型,就返回什么样的对象
public static <T> T toObject(String json,Class<T> targer){
if (StringUtils.isEmpty(json)||targer==null) {
throw new RuntimeException("参数不能为空");
}
try {
return mapper.readValue(json, targer);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}}
自定义缓存注解
如何管制 哪些办法须要应用缓存?
解决方案:采纳自定义注解的模式 进行定义 如果办法执行须要应用缓存,则标识
对于注解的阐明:
1.注解名称:
2.属性参数:
key:应该由用户本人手动增加 个别增加业务名称 之后动静拼接造成惟一的
seconds:用户能够指定数据的超时工夫
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheFind {
public String preKey();//用户标识key的前缀
public int seconds() default 0;//如果用户不写示意不须要超时,如果写了以用户为准
}
开始应用注解
实现代码
@Aspect //我是一个aop的切面类
@Component//将类交给spring容器治理
public class CacheAOP {
@Autowired
private Jedis jedis;
/**
* 1.动静生成key preKey+用户参数数组
* @param joinPoint
* @return
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){
System.out.println("注解拦挡");
Object result=null;
try {
//1.拼接Redis存储数据的key
Object[] args = joinPoint.getArgs();
String key = cacheFind.preKey()+"::" + Arrays.toString(args);
//2.查问redis
if(jedis.exists(key)){
//redis中有记录
String json=jedis.get(key);
//将数据转化成须要的类型——办法的返回值类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class type = signature.getReturnType();
result = ObjectMapperUtil.toObject(json,type);
}else{
//不存在 查询数据库
result=joinPoint.proceed();//执行指标办法
//将查问后果保留到Redis中
String json= ObjectMapperUtil.toJson(result);
//判断数据是否须要超时工夫
if(cacheFind.seconds()>0){
jedis.setex(key,cacheFind.seconds(),json);
}else {
jedis.set(key,json);
}
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
}
发表回复