通过AOP改善项目中缓存策略
最近项目中要添加memcached来改善系统的访问速度
memcached是个很好用的缓存系统,也很好搭建和维护,这里就不做介绍
下面主要介绍一下怎么来在项目中添加memcached
现在想起来的有两种方式添加
1、在需要添加memcached的方法中都显示的添加和memcached有关的方法
2、使用aop的方式来添加memcached的策略
两个方法的优缺点:
方法一:
优点:直观,明确,让人一下就能看到缓存的存在
缺点:代码编写量比较大。修改起来比较痛苦,比如那一天换缓存的实现方式或者不使用缓存了,需要修改很多方法
方法二:
优点:代码量少,易于维护
缺点:不够直观。并且由于是方法都是以前存在的,也需要修改以前的代码,让他们符合一定的规律,这样才能统一处理
下面主要讲一讲通过AOP方式实现缓存的策略
思路如下:
1、aop处理缓存,得区分出来被代理的方法哪些是更新、添加、删除、查询的方法
更新和添加方法的话,直接调用set方法进行更新
删除方法的时候,调用delete方法进行删除
查询方法,查看是否有缓存,如果没有的话,从数据库中查询到,然后添加到缓存中
2、把以前的方法进行分类,那些方法的查询可以继承一个查询父类(该查询父类可以拿到关键的查询条件),那些方法能继承统一的修改父类(修改父类也能拿到关键的查询条件)。其中查询条件作为关键key来存入到缓存中
具体实现可以查看源代码,代码已经上传
主要实现代码如下:
1、CacheUserAop
针对第一个参数为user对象的操作缓存的aop
写道
package com.wangcanpei.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import com.wangcanpei.model.User;
import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;
/**
* 针对第一个参数为user对象的操作缓存的aop
* @author wangcanpei
*
*/
public class CacheUserAop {
private static final Log log=LogFactory.getLog(CacheUserAop.class);
/**
* 在新增数据的时候,调用的aop,作用是往缓存中新增数据
* @param point
* @return
*/
public Object addCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.set(key, user);
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 在删除数据的时候,调用的aop,作用是删除缓存里的数据
* @param point
* @return
*/
public Object delCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.delete(key);
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(User user){
String key="aopTest";
key=key+"&"+user.getName();
return MD5.getMD5(key);
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import com.wangcanpei.model.User;
import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;
/**
* 针对第一个参数为user对象的操作缓存的aop
* @author wangcanpei
*
*/
public class CacheUserAop {
private static final Log log=LogFactory.getLog(CacheUserAop.class);
/**
* 在新增数据的时候,调用的aop,作用是往缓存中新增数据
* @param point
* @return
*/
public Object addCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.set(key, user);
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 在删除数据的时候,调用的aop,作用是删除缓存里的数据
* @param point
* @return
*/
public Object delCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.delete(key);
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(User user){
String key="aopTest";
key=key+"&"+user.getName();
return MD5.getMD5(key);
}
}
2、SelectCacheAop 针对第一个参数为String的查询aop
写道
package com.wangcanpei.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;
/**
* 针对第一个参数为String的查询aop
* @author wangcanpei
*
*/
public class SelectCacheAop {
private static final Log log=LogFactory.getLog(SelectCacheAop.class);
/**
* 在查询数据的时候使用,并且第一个参数就是查询条件的
* @param point
* @return
*/
public Object select(ProceedingJoinPoint point){
Object ret=null;
String name=(String)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(point,name);
log.error("key:"+key);
Object obj=MemcachedClientUtil.get(key);
if(null!=obj){
return obj;
}
return point.proceed();
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(JoinPoint point,String name){
String key="aopTest";
key=key+"&"+name;
return MD5.getMD5(key);
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;
/**
* 针对第一个参数为String的查询aop
* @author wangcanpei
*
*/
public class SelectCacheAop {
private static final Log log=LogFactory.getLog(SelectCacheAop.class);
/**
* 在查询数据的时候使用,并且第一个参数就是查询条件的
* @param point
* @return
*/
public Object select(ProceedingJoinPoint point){
Object ret=null;
String name=(String)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(point,name);
log.error("key:"+key);
Object obj=MemcachedClientUtil.get(key);
if(null!=obj){
return obj;
}
return point.proceed();
} catch (Throwable e) {
log.error(e);
}
return ret;
}
/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(JoinPoint point,String name){
String key="aopTest";
key=key+"&"+name;
return MD5.getMD5(key);
}
}
配置文件
写道
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<bean id="cacheUserAop" class="com.wangcanpei.aop.CacheUserAop" />
<bean id="selectCacheAop" class="com.wangcanpei.aop.SelectCacheAop" />
<aop:config>
<aop:aspect id="TestAspect" ref="cacheUserAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->
<aop:pointcut id="userAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="userAop" method="addCacheAfter"/>
<aop:pointcut id="deleteuserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="deleteuserAop" method="delCacheAfter"/>
</aop:aspect>
<aop:aspect id="selectAspect" ref="selectCacheAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->
<aop:pointcut id="seluserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(String,..))" />
<aop:around pointcut-ref="seluserAop" method="select"/>
</aop:aspect>
</aop:config>
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<bean id="cacheUserAop" class="com.wangcanpei.aop.CacheUserAop" />
<bean id="selectCacheAop" class="com.wangcanpei.aop.SelectCacheAop" />
<aop:config>
<aop:aspect id="TestAspect" ref="cacheUserAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->
<aop:pointcut id="userAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="userAop" method="addCacheAfter"/>
<aop:pointcut id="deleteuserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="deleteuserAop" method="delCacheAfter"/>
</aop:aspect>
<aop:aspect id="selectAspect" ref="selectCacheAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->
<aop:pointcut id="seluserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(String,..))" />
<aop:around pointcut-ref="seluserAop" method="select"/>
</aop:aspect>
</aop:config>
</beans>
相关推荐
根据实际需求,还可以调整缓存策略,例如添加缓存更新和删除的逻辑,以及处理并发问题。 通过以上步骤,你已经成功地将Spring AOP与EhCache集成,实现了一个简单的缓存实例。这种方式可以显著提高高访问量场景下的...
总结起来,这个解决方案通过Spring AOP和ehCache,提供了一种优雅且高效的缓存策略。拦截器确保了缓存的自动管理和维护,而ehCache的使用则提供了高性能的对象缓存能力。当数据库操作发生时,缓存能及时更新,从而...
在本文中,我们将深入探讨如何在Spring框架中集成并使用AOP(面向切面编程)来实现对EHCache的高效管理。Spring是一个广泛使用的Java应用框架,它提供了强大的依赖注入和面向切面编程功能。而EHCache是一款流行、高...
在这个场景中,我们将探讨如何在Swoft2中实现一个非侵入式的缓存策略,使得缓存功能可以无缝地融入到现有的业务逻辑中,而不需要修改被拦截的方法或类。 首先,我们需要理解非侵入式缓存的概念。非侵入式缓存意味着...
Spring AOP 和 EhCache 结合使用提供了一个简单而有效的缓存解决方案,主要目的是优化系统性能,减少对数据库的频繁访问。下面将详细解释这个解决方案的关键组成部分。 首先,EhCache 是一个广泛使用的开源 Java ...
标题 "使用Spring AOP对Web应用数据进行Memcached缓存" 涉及到的关键技术是Spring AOP(面向切面编程)和Memcached,这是一种常见的高性能、分布式内存对象...通过不断优化和调整缓存策略,可以进一步提升系统性能。
在实际项目中,可能还需要考虑其他因素,如缓存策略、性能优化以及与其他安全框架(如Spring Security)的协同工作等。总的来说,Spring AOP与Oracle的数据权限控制相结合,为大型企业应用提供了强大的安全保障。
这样,我们既利用了Redis的高速缓存能力,又利用了Spring AOP的无侵入性,实现了高效且灵活的缓存策略。 通过以上描述,我们可以看到"redis集成spring实现aop"是一个涉及多方面技术融合的过程,包括Redis数据库的...
它可能包含添加、删除、更新和查找缓存项的函数,同时处理Ehcache的一些配置和管理任务,比如设置缓存策略(如过期时间、大小限制等)。 3. **MethodCache.java**:这个类可能进一步细化了缓存管理,专注于方法级别...
AutoLoadCache是一个强大的Java缓存管理工具,它利用AOP(面向切面编程)和注解技术来提供高效且灵活的缓存策略。在高并发的Web应用中,缓存管理是性能优化的关键部分,而AutoLoadCache正是为了解决这个问题而设计的...
此外,该框架还支持动态调整缓存策略,能够更好地适应不断变化的应用需求。 综上所述,基于AOP的智能Web缓存框架ABWC不仅解决了传统缓存技术中存在的问题,而且还提供了一个高效、灵活且易于集成的解决方案,对于...
3. **第六章_cache-demo.zip**:此示例可能进一步扩展了缓存相关的实现,包括不同类型的缓存策略、缓存更新和过期策略等。 4. **第二章_execution-demo.zip**:这个代码可能演示了如何通过`@Around`通知和`@...
Spring AOP可以帮助我们实现缓存策略: 1. **选择缓存库**:Spring支持多种缓存实现,如 EhCache、Redis 或 Hazelcast。首先需要引入相应的库并配置缓存管理器。 2. **定义缓存注解**:Spring 提供了 `@Cacheable`...
在IT行业中,面向切面编程(Aspect Oriented Programming,AOP)是一种强大的设计模式,它允许程序员将关注点从核心业务逻辑中分离出来,比如...同时,通过EhCache的配置,我们可以实现高效的缓存策略,提升系统性能。
接下来,我们来看看如何在Spring中使用AOP实现缓存。首先,我们需要在配置文件中启用AOP代理,并定义一个缓存注解,例如`@Cacheable`。这个注解可以标记在方法上,表示该方法的返回结果应当被缓存。当相同的方法被...
这里提到的`ehcache.xml`是EHCache的配置文件,其中定义了具体的缓存策略和缓存区域。例如: ```xml ``` 然后,我们可以创建一个切面(Aspect)来定义哪些方法需要被缓存。在Spring AOP中,可以使用`@...
在IT行业中,AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它旨在提高...通过对不同类型的AOP通知的理解和实践,我们可以更好地设计和实现权限验证系统,为应用程序提供强大而灵活的安全保障。
通过这个项目,开发者可以全面了解如何在SpringBoot环境中利用AOP和Redis实现高效的缓存策略,同时掌握Spring Data JPA与MySQL的集成,以及API文档的自动化生成。对于希望提升微服务开发技能的程序员来说,这是一个...
7. **性能优化**:为了优化读写分离的效果,我们还需要考虑一些其他因素,比如数据库的负载均衡、缓存策略、读写比例调整等。例如,可以使用负载均衡器分发读请求,或者采用Redis等缓存技术减少对数据库的直接访问。...