需求是这样的,业务代码需要使用到缓存功能以减少数据库压力,使用redis来实现,并且需要生成缓存的key由方法的传参拼接而成(貌似也只能这样才能保证同样的select查询可以使用缓存),简单的方式就是在需要缓存的方法内加上大概这样的逻辑:查询缓存--->没有则查询数据库 --->查询结果以key-value形式放入缓存,这样对业务代码造成了侵入,并且产生大量重复的代码,很不优雅,所以决定自己封装一个缓存模块,在需要缓存的地方只需要加入一个注解即可。

  首先自定义一个注解

package com.example.test.aspect;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MyCache { String value() default "";
}

  定义切面

package com.example.test.aspect;

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.aspectj.lang.reflect.MethodSignature;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Component
@Aspect
public class MyAspect { //切入点,带有Myche注解并且是UserService类下的方法
@Pointcut("@annotation(com.example.test.aspect.MyCache)&&execution(* com.example.test.service.UserService.*(..))")
public void pointCut(){}; @Around("pointCut()")
public Object cache(ProceedingJoinPoint joinPoint)throws Throwable{
//获取方法签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取目标方法
Method method = methodSignature.getMethod();
// Method method2 = joinPoint.getTarget().getClass().getMethod(methodSignature.getName(),methodSignature.getParameterTypes());
//获取方法上的注解
MyCache myCache = method.getDeclaredAnnotation(MyCache.class);
//得到el表达式
String el = myCache.value();
//解析el表达式,将#id等替换为参数值
ExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression(el);
EvaluationContext context = new StandardEvaluationContext();
String[] parameterNames = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
for (int i = 0; i <parameterNames.length ; i++) {
context.setVariable(parameterNames[i],args[i]);
}
String key = expression.getValue(context).toString();
System.out.println(key);
//根据key从缓存中拿数据,这里省略 //如果缓存中没有则执行目标方法
Object o = joinPoint.proceed();
//将结果放入缓存,这里省略 return o; }
}

  测试的service

package com.example.test.service;

import com.example.test.aspect.MyCache;
import org.springframework.stereotype.Service; @Service
public class UserService implements UserServiceInterface{ @MyCache("'asd_' + #id")
@Override
public void addUser(String id,String name){
System.out.println(id + "----" + name);
}
}

  测试类,这里是springboot项目

package com.example.test;

import com.example.test.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplicationTests { @Autowired
private UserService userService; @Test
public void contextLoads() {
System.out.println(userService.getClass().getName()); userService.addUser("12345" ,"zhagnsan");
} }

  执行结果如下:

  修改UserService上的注解为:"'asd_' + #id + '_' + #name",结果如下

使用spring EL表达式+自定义切面封装缓存模块的更多相关文章

  1. Spring EL表达式和资源调用

    Spring EL表达式     Spring EL-Spring表达式语言,支持在xml和注解中使用表达式,类似于在jsp的EL表达式语言.     Spring 开发中经常涉及调用各种资源的情况, ...

  2. 把功能强大的Spring EL表达式应用在.net平台

    Spring EL 表达式是什么? Spring3中引入了Spring表达式语言—SpringEL,SpEL是一种强大,简洁的装配Bean的方式,他可以通过运行期间执行的表达式将值装配到我们的属性或构 ...

  3. EL表达式---自定义函数(转)

    EL表达式---自定义函数(转) 有看到一个有趣的应用了,转下来,呵呵!! 1.定义类MyFunction(注意:方法必须为 public static) package com.tgb.jstl;  ...

  4. Spring 在 xml配置文件 或 annotation 注解中 运用Spring EL表达式

    Spring  EL 一:在Spring xml 配置文件中运用   Spring EL Spring EL 采用 #{Sp Expression  Language} 即 #{spring表达式} ...

  5. EL表达式自定义函数

    表达式语言除了可以使用基本的运算符外,还可以使用自定义函数.通过使用自定义函数,加强了表达式语言的功能. EL表达式函数,主要功能是完成对数据的修改,统一化格式: 步骤 1.开发函数处理类,处理类就是 ...

  6. 解决spring el表达式不起作用

    el表达式不起作用,如下图所示 现象: 在显示页面中加入: <%@ page isELIgnored="false" %>就OK了 参考:http://bbs.csdn ...

  7. java MVEL2/Spring EL表达式、直接调用、反射性能实测

    import java.io.Serializable; import java.lang.reflect.Field; import java.util.HashMap; import java.u ...

  8. spring EL表达式,null-safe表达式

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://ww ...

  9. Spring整合Shiro并扩展使用EL表达式

    Shiro是一个轻量级的权限控制框架,应用非常广泛.本文的重点是介绍Spring整合Shiro,并通过扩展使用Spring的EL表达式,使@RequiresRoles等支持动态的参数.对Shiro的介 ...

随机推荐

  1. 大文件webuploader的基本使用

    webuploader的简单使用 需要的文件   自备  百度很多 webuploader.js  uploader.swf  jQuery <!DOCTYPE html> <htm ...

  2. spring p 标签

    需要引入命名空间 xmlns:p="http://www.springframework.org/schema/p" p 是什么含义 p 是 property 的缩写,为了简化be ...

  3. 使用工厂方法配置bean的两种方式

    1.使用静态工厂方法: 对应的配置.xml文件: 2.通过实例工厂的方法来配置bean: 对应的xml文件:

  4. session token防表单重提

    1.表单页面初始化前,先在session存入一个token值,随后把token存放在表单页面隐藏表单域内,开始初始化: 在表单页初始化前,调用ajax请求,在后台生成token,并返回至表单页 fun ...

  5. 11i AP & GL 月末对账时常用系统报表

    11i AP & GL 月末对账时常用系统报表  http://www.cnblogs.com/benio/archive/2011/10/14/2212169.html AP: 1.Invo ...

  6. Spring Boot 应用系列 2 -- Spring Boot 2 整合MyBatis和Druid

    本系列将分别演示单数据源和多数据源的配置和应用,本文先演示单数据源(MySQL)的配置. 1. pom.xml文件配置 需要在dependencies节点添加: <!-- MySQL --> ...

  7. CSharp程序员学Android开发---3.Android内部元素不填充BUG

    最近公司组织项目组成员开发一个Android项目的Demo,之前没有人有Andoid方面的开发经验,都是开发C#的. 虽说项目要求并不是很高,但是对于没有这方面经验的人来说,第一步是最困难的. 项目历 ...

  8. winform之combobox

    绑定键值对: ArrayList mylist = new ArrayList(); mylist.Add(new DictionaryEntry("WinFormURL", &q ...

  9. Angular6 学习笔记——组件详解之组件通讯

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  10. Cesium简介 [转]

    http://www.cnblogs.com/laixiangran/p/4984522.html 一.Cesium介绍 Cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎. ...