一般情况下,java程序取一条数据是直接从数据库中去取,当数据库达到一定的连接数时,就会处于排队等待状态,
某些在一定时间内不会发生变化的数据,完全没必要每次都从数据库中去取,
使用spring-aop + memcached 技术,取数据时,先从缓存中去取,缓存中如果存在,直接返回结果,无需访问数据库;如果缓存中不存在,再访问数据库,并把这条数据保存到缓存中,当程序下次再访问时,就可以取到缓存中的值了。这样不但可以大大减少访问数据库的次数(减轻数据的负担),而且可以提高程序的运行效率,因为memecached 是采用key - value 方法存取数据的。
使用memcached时特别需要注意的是:
1.当某条数据发生变化时,一定要更新cache中的这条记录;
2.设置key时一定要唯一,
一般是通过prefix + uuid 保证唯一,prefix一般使用数据库的表名
下面来介绍一下spring-aop + memcached 技术的简单实现:
1.定义注解类 @Cache
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {
/**
* key的前缀
* @return
*/
String prefix();
/**
* 指定哪个参数值做Key,与cacheKey两者选一,如果都有输入,默认使用indexKey
* @return
*/
int indexKey() default 0;
/**
* 缓存有效期 1000*60*60*2=2小时
* @return
*/
long expiration() default 1000 * 60 * 60 * 2;
}
2.定义切入点类 CachePoint,这个类一定要与上面的注解类在同一包目录下
@Component
@Aspect
public class CachePoint {
@Autowired
private CacheService cacheService;
/**
* @Pointcut("@annotation(Cache)") 表示定义切入点所有带有@Cache注解的方法
*/
@Pointcut("@annotation(Cache)")
public void queryCache(){
System.out.println("此输出将不会执行...");
}
@Around("queryCache()")
public Object getByCache(ProceedingJoinPoint pjp) throws Throwable {
// 1.查询缓存的值
Object obj = cacheService.getKey("test_1000123456");
// 2.如果缓存中不存在,则查询mysql数据库
if (null==obj) {
obj = pjp.proceed();
// 3.将obj的值写入缓存
cacheService.setKey("test_1000123456", obj);
}
return obj;
}
}
3.编写memcached 的业务类
@Component("cacheService")
public class CacheService {
/**
* 读取缓存的方法
* @param key
* @return
*/
public Object getKey(String key) {
System.out.println("query from memcached");
return null;
}
/**
* 写入缓存的方法
* @param key
* @param obj
*/
public void setKey(String key, Object obj) {
}
/**
* 删除缓存的方法
* @param key
*/
public void delete(String key) {
}
}
4.Dao 的实现层添加注解
@Component("testDao")
public class TestDaoImpl implements TestDao {
/**
* 此处将使用 prefix + indexKey 作为缓存的key,即 test_ + uuid
*/
@Cache(indexKey=1, prefix="test_")
@Override
public String query(String uuid) {
System.out.println("query from mysql");
return "caoxiaobo";
}
}
配置文件spring-aop.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 自动扫描 -->
<context:component-scan base-package="com.spring.*" />
<!-- 开启注入注解扫描 -->
<context:annotation-config/>
<aop:aspectj-autoproxy/>
</bea
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-aop.xml" })
public class SprintAopAndCacheTest {
@Autowired
TestService testService;
@Test
public void test() {
String name = testService.query("1000123456");
System.out.println(name);
}
}