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 />
而由於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>
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;
- }
- }
緩存操作通常是對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);
- }
- }