simple-spring-memcached簡介
memcached是一款非常優秀的分布式緩存工具,有效提升了按主鍵檢索數據的性能問題。而simple-spring-memcached組件通過與spring框架整合,讓memcached的調用變得更加簡單。
simple-spring-memcached本質上是采用了AOP的方式來實現緩存的調用和管理,其核心組件聲明了一些Advice,當遇到相應的切入點時,會執行這些Advice來對memcached加以管理。
切入點是通過標簽的方式來進行聲明的,在項目開發時,通常在DAO的方法上加以相應的標簽描述,來表示組件對該方法的攔截
組件所提供的切入點主要包括以下幾種:
ReadThroughSingleCache、ReadThroughMultiCache、ReadThroughAssignCache
當遇到查詢方法聲明這些切入點時,組件首先會從緩存中讀取數據,取到數據則跳過查詢方法,直接返回。
取不到數據在執行查詢方法,并將查詢結果放入緩存,以便下一次獲取。
InvalidateSingleCache、InvalidateMultiCache、InvalidateAssignCache
當遇到刪除方法聲明這些切入點時,組件會刪除緩存中的對應實體
UpdateSingleCache、UpdateMultiCache、UpdateAssignCache
當遇到更新方法聲明這些切入點是,組件會更新緩存中對應的實體,以便下次從緩存中讀取出的數據狀態是最新的
simple-spring-memcached本身并不提供cache機制的實現,只是為了cache的調用更加簡單而設計的。
在cache的實現上使用的是第三方組件(如x-memcached和spy-memcached),官方給出了針對這兩種組件的相關配置
http://code.google.com/p/simple-spring-memcached/wiki/Getting_Started
simple-spring-memcached的使用:
1.首先在Spring配置文件中加入如下兩句:
<import resource="simplesm-context.xml" /> <aop:aspectj-autoproxy />simplesm-context.xml封裝在simple-spring-memcached-*.jar文件當中,主要用來加載組件核心的Advice,供程序調度使用。
而由于simple-spring-memcached主要是基于AOP的代理,所以加入<aop:aspectj-autoproxy />讓代理機制起到作用。
2.定義memcached客戶端
memcached比較常用的java客戶端有兩種,spymemcached和xmemcached,xmemcached支持多線程
<bean name="defaultMemcachedClient" class="com.google.code.ssm.CacheFactory"> <property name="cacheClientFactory"> <bean class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl" /> </property> <property name="addressProvider"> <bean class="com.google.code.ssm.config.DefaultAddressProvider"> <property name="address" value="192.168.7.131:11211" /> </bean> </property> <property name="configuration"> <bean class="com.google.code.ssm.providers.CacheConfiguration"> <property name="consistentHashing" value="true" /> </bean> </property> </bean>com.google.code.ssm.CacheFactory是一個FactoryBean,會返回Cache實體供Advice使用
address屬性定義了緩存節點的IP地址和端口號
consistentHashing屬性定義了緩存節點的查找方法
3.實體的定義
memcached相當于一個功能強大的Map,通過Key/Value的形式來緩存POJO實體,在定義實體的時候,可通過@CacheKeyMethod標簽來為實體指定Key值,同時實體及實體的每個成員變量必須是可序列化的,可實現Serializable接口,或通過Externalizable接口來為實體指定序列化方法。
public class User implements Serializable { private static final long serialVersionUID = 7517080513591583073L; private String userId; private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @CacheKeyMethod public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } }4.DAO的定義
緩存操作通常是對DAO的方法進行攔截,加入必要的通知以達到增刪改查的效果
切入點的聲明主要通過之前提到的標簽來實現
public class UserDaoImpl implements IUserDao { private static final String NAMESPACE="ns"; private Map<String,User> users=new HashMap<String,User>(); @Override public void saveUser(User user) { users.put(user.getUserId(), user); } /** * 當執行getById查詢方法時,系統首先會從緩存中獲取userId對應的實體 * 如果實體還沒有被緩存,則執行查詢方法并將查詢結果放入緩存中 */ @Override @ReadThroughSingleCache(namespace = NAMESPACE, expiration = 3600) public User getById(@ParameterValueKeyProvider String userId) { System.out.println(userId); return users.get(userId); } /** * 當執行updateUser方法時,系統會更新緩存中userId對應的實體 * 將實體內容更新成@*DataUpdateContent標簽所描述的實體 */ @UpdateSingleCache(namespace = NAMESPACE, expiration = 3600) @Override public void updateUser(@ParameterValueKeyProvider @ParameterDataUpdateContent User user) { users.put(user.getUserId(), user); } /** * 當執行deleteUser方法時,系統會刪除緩存中userId對應的實體 */ @InvalidateSingleCache(namespace = NAMESPACE) @Override public void deleteUser(@ParameterValueKeyProvider String userId) { users.remove(userId); } }