目录
一、需求说明
为了简化代码,提示可读性需要针对优先读缓存,如果缓存没有则插入数据库然后再将数据写入缓存并返回。
根据这个需求我们可以基于Spring AOP 去实现。但是有一个问题,缓存的key是一个动态值,对于不同入参它的key是不同的。我们可以使用SpringEL 表达式去解决这个问题。
预期的效果是:
@Cache(prefix = "test", value = "#bizId", expire = CacheTime.CACHE_EXP_DAY) public Object queryFromCache(Long bizId)
二、Spring AOP
首先我们先了解一下Spring AOP的基础知识
2.1 AOP切点指示器
AspectJ 指示器 | 描述 |
args() | 限制连接点匹配参数为执行类型的执行方法 |
@args() | 限制连接点匹配参数由执行注解标注的执行方法 |
execution() | 匹配连接点的执行方法 |
this() | 限制连接点匹配AOP代理的Bean引用类型为指定类型的Bean |
target() | 限制连接点匹配目标对象为指定类型的类 |
@target() | 限制连接点匹配目标对象被指定的注解标注的类 |
within() | 限制连接点匹配匹配指定的类型 |
@within() | 限制连接点匹配指定注解标注的类型 |
@annotation | 限制匹配带有指定注解的连接点 |
Spring AOP 中常用的是:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
2.2 AOP表达式
表达式 | 说明 |
execution("* *.*(..)") | 匹配所有 |
execution("* *.set*(..)) | 匹配所有以set开头的方法 |
execution("* com.david.biz.service.impl.*(..)) | 匹配指定包下所有的方法 |
execution("* com.david..*(..)") | 匹配指定包以及其子包下的所有方法 |
execution("* com.david..*(java.lang.String)) | 匹配指定包以及其子包下 参数类型为String 的方法 |
2.3、Spring AOP通知类型
通知类型 | 说明 |
前置通知(Before) | 在目标方法被调用之前调用通知功能。 |
后置通知(After) | 在目标方法完成之后调用通知,此时不会关心方法的输出是什么 |
返回通知(After-returning) | 在目标方法成功执行之后调用通知。 |
异常通知(After-throwing) | 目标方法抛出异常后调用通知。 |
环绕通知(Around) | 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。 |
2.4、示例代码
/**
* execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
*arg() 限制连接点匹配参数为指定类型的执行方法
*@args() 限制连接点匹配参数由执行注解标注的执行
*execution() 用于匹配连接点的执行方法
*this() 限制连接点匹配AOP代理的Bean引用为执行类型的类
*target() 限制连接点匹配目标对象为指定类型的类
*@target() 限制连接点匹配特定的执行对象,这些对象应具备指定的注解类型
*@annotation()限制匹配带有指定注解的连接点
*
*
*
* @author zhangwei_david
* @version $Id: LogAspect.java, v 0.1 2014年11月29日 下午1:10:13 zhangwei_david Exp $
*/
@Component
@Aspect
public class LogAspect {
private static final Logger logger = LogManager.getLogger(LogAspect.class);
/*