spring是一个轻量级开源框架,以IoC(Inverse of Control:控制反转)和AOP(Aspect Oriented Programming:面向切面编程)为内核,
兼具功能强大的的原生展现层spring mvc,原生持久层spring jdbc和原生业务层等技术,并且以海纳百川的胸怀整合了开源世界里众多
著名的第三方框架和类库,已经逐渐成为世界上使用最多的JavaEE企业级应用开源框架.
现在我们已经学会了如何使用开箱即用的spring cache,他也基本能够满足一般的需求,但是当你的用户量上去或者性能跟不上的时候,
你就需要自定义你的缓存方案了.如何利用spring cache提供的扩展点实现我们自己的缓存,前提是在不改原来已有代码的情况下进行扩展.
点击链接下载源码!
兼具功能强大的的原生展现层spring mvc,原生持久层spring jdbc和原生业务层等技术,并且以海纳百川的胸怀整合了开源世界里众多
著名的第三方框架和类库,已经逐渐成为世界上使用最多的JavaEE企业级应用开源框架.
现在我们已经学会了如何使用开箱即用的spring cache,他也基本能够满足一般的需求,但是当你的用户量上去或者性能跟不上的时候,
你就需要自定义你的缓存方案了.如何利用spring cache提供的扩展点实现我们自己的缓存,前提是在不改原来已有代码的情况下进行扩展.
1.首先,我们需要提供一个CacheManager接口的实现,这个接口告诉spring有哪些cache实例,spring会根据cache的名字查找cache的实例.
<span style="font-size:12px;">package com.ilucky.spring.cache.ilucky;
import java.util.Collection;
import org.springframework.cache.support.AbstractCacheManager;
/**
* @author IluckySi
* @date 20140615
*/
public class IluckyCacheManager extends AbstractCacheManager {
private Collection<? extends IluckyCache> caches;
/**
* JVM加载spring配置文件时, 通过set方法注入本类的参数.
* @param caches
*/
public void setCaches(Collection<? extends IluckyCache> caches) {
this.caches = caches;
}
@Override
public Collection<? extends IluckyCache> loadCaches() {
return caches;
}
}
</span>
2.另外,还需要实现Cache接口,Cache接口负责实际的缓存逻辑,例如增加键值对、存储、查询和清空等.
<span style="font-size:12px;">package com.ilucky.spring.cache.ilucky;
import java.util.HashMap;
import java.util.Map;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import com.ilucky.spring.cache.model.User;
/**
* @author IluckySi
* @date 20140615
*/
public class IluckyCache implements Cache {
private String name;
private Map<String, User> store = new HashMap<String, User>();
public IluckyCache() {
}
public IluckyCache(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
/**
* JVM加载spring配置文件时, 通过set方法注入本类的参数.
* @param userDao
*/
public void setName(String name) {
this.name = name;
}
@Override
public Object getNativeCache() {
return store;
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper result = null;
User user = store.get(key);
if(user != null) {
System.out.println("缓存中存在key=" + key + "的User!");
result = new SimpleValueWrapper(user);
} else {
System.out.println("缓存中不存在key=" + key + "的Uesr!");
}
return result;
}
@Override
public void put(Object key, Object value) {
User user = (User)value;
store.put((String)key, user);
System.out.println("向缓存中成功加入一条数据: " + user);
}
@Override
public void evict(Object key) {
}
@Override
public void clear() {
}
}
</span>
3.创建spring配置文件,配置自定义的缓存管理器和bean之间的依赖关系,直接看代码spring-cahce.xml.
<?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:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
<!-- 应用spring cache注解功能 -->
<cache:annotation-driven />
<!-- 创建spring cache bean -->
<bean id="cacheManager" class="com.ilucky.spring.cache.ilucky.IluckyCacheManager">
<property name="caches">
<set>
<!--配置自定义缓存 -->
<bean class="com.ilucky.spring.cache.ilucky.IluckyCache" p:name="data" />
</set>
</property>
</bean>
<!-- 创建User Dao bean -->
<bean id="userDao" class="com.ilucky.spring.cache.dao.impl.UserDaoImpl" ></bean>
<!-- 创建User Service bean -->
<bean id="userService" class="com.ilucky.spring.cache.service.impl.UserServiceImpl" >
<property name="userDao" >
<ref bean="userDao"></ref>
</property>
</bean>
</beans>
4.最后通过测试类测试spring缓存机制是否生效,直接看代码MainTest.
<span style="font-size:12px;">package com.ilucky.spring.cache;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ilucky.spring.cache.ilucky.IluckyCache;
import com.ilucky.spring.cache.ilucky.IluckyCacheManager;
import com.ilucky.spring.cache.model.User;
import com.ilucky.spring.cache.service.UserService;
/**
* @author IluckySi
* @date 20140615
* 测试spring缓存机制是否生效.
*/
public class MainTest {
public static void main(String[] args) {
//加载ClassPath路径下的spring配置文件, 并获取service bean. 注意: 我们可以获取spring配置文件中配置的任何bean.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-cache.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println("service bean: " + userService);
IluckyCacheManager cacheManager = context.getBean("cacheManager", IluckyCacheManager.class);
System.out.println("service bean: " + cacheManager);
System.out.println("--------------bean初始化完成---------------");
//验证id.length() < =5的数据不会放入缓存中.
userService.add(new User("1", "Ilucky", "Ilucky1"));
userService.find("1");
userService.add(new User("111111", "Ilucky", "Ilucky111111"));
userService.find("111111");
//验证
userService.find("111111");
//遍历缓存(两种方案).
System.out.println("---------------第一种方案获取缓存---------------");
Collection<String> cacheNames = cacheManager.getCacheNames();
Iterator<String> iterator = cacheNames.iterator();
while(iterator.hasNext()) {
String cacheName = iterator.next();
System.out.println("缓存名称: " + cacheName);
IluckyCache iluckyCache = (IluckyCache)cacheManager.getCache(cacheName);
Map<String, User> map = (Map<String, User>) iluckyCache.getNativeCache();
for(Entry<String, User> entry : map.entrySet()) {
System.out.println("--------" +entry.getValue());
}
}
System.out.println("---------------第二种方案获取缓存---------------");
Collection<? extends IluckyCache> caches = cacheManager.loadCaches();
Iterator<? extends IluckyCache> it = caches.iterator();
while(it.hasNext()) {
IluckyCache iluckyCache = it.next();
System.out.println("缓存名称: " + iluckyCache.getName());
Map<String, User> map = (Map<String, User>) iluckyCache.getNativeCache();
for(Entry<String, User> entry : map.entrySet()) {
System.out.println("--------" +entry.getValue());
}
}
}
}
/**
spring缓存分为两种:方法和数据,如果方法被清除了,需要重新从数据库获取数据放入缓存,另外只有方法加入了缓存才可以获取缓存中的数据.
输出结果:
service bean: com.ilucky.spring.cache.service.impl.UserServiceImpl@92dcdb
service bean: com.ilucky.spring.cache.ilucky.IluckyCacheManager@1e1be92
--------------bean初始化完成---------------
UserService: method- add(User user)
UserDao method- add(User user)
UserService: method-find(String id)
UserDao method- find(String id)
UserService: method- add(User user)
UserDao method- add(User user)
缓存中不存在key=111111的Uesr!
UserService: method-find(String id)
UserDao method- find(String id)
向缓存中成功加入一条数据: 111111-Ilucky-Ilucky111111
缓存中存在key=111111的User!
---------------第一种方案获取缓存---------------
缓存名称: data
--------111111-Ilucky-Ilucky111111
---------------第二种方案获取缓存---------------
缓存名称: data
--------111111-Ilucky-Ilucky111111
帮助分析:
执行第一个userService.find("111111")方法时输出如下:
缓存中不存在key=111111的Uesr!
UserService: method-find(String id)
UserDao method- find(String id)
向缓存中成功加入一条数据: 111111-Ilucky-Ilucky111111
即:在执行find方法前,通过AOP机制首先从缓存中获取数据,如果获取不到,再从数据库获取,
最后再通过AOP机制将从数据库获取的数据放入缓存中.
执行第二个userService.find("111111")方法时输出如下:
缓存中存在key=111111的User!
即:在执行find方法前,通过AOP机制首先从缓存中获取数据,如果有直接返回.
*/
</span>
注意:spring缓存分为两种:方法和数据,如果方法被清除了,需要重新从数据库获取数据放入缓存,另外只有方法加入了缓存才可以获取缓存中的数据.点击链接下载源码!