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; }}