`

SpringAOP结合ehCache实现简单缓存实例

阅读更多
AOP,当然需要拦截器,这里需要2个拦截器:
一个是方法执行前查找缓存的拦截器;(query方法执行前先查找是否有缓存,如果有,走缓存,如果没有,执行方法,并且把结果缓存)
另一个是方法执行后销毁缓存的拦截器;(update,insert,delete等方法执行后需要销毁缓存)

---------------------------------------------------------------------------------------------------------------------------------------

方法执行前的拦截器MethodCacheInterceptor.java:
package ehcache;

import java.io.Serializable;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean {
	private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);

	private Cache cache;

	/**
	 * 设置缓存名
	 */
	public void setCache(Cache cache) {
		this.cache = cache;
	}

	/**
	 * 检查是否提供必要参数。
	 */
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(cache, "A cache is required. Use setCache(Cache) to provide one.");
	}

	/**
	 * 主方法 如果某方法可被缓存就缓存其结果 方法结果必须是可序列化的(serializable)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		String targetName = invocation.getThis().getClass().getName();
		String methodName = invocation.getMethod().getName();
		Object[] arguments = invocation.getArguments();
		Object result;

		logger.debug("looking for method result in cache");
		String cacheKey = getCacheKey(targetName, methodName, arguments);
		Element element = cache.get(cacheKey);
		if (element == null) {
			// call target/sub-interceptor
			logger.debug("calling intercepted method");
			result = invocation.proceed();
			// cache method result
			logger.debug("caching result");
			element = new Element(cacheKey, (Serializable) result);
			cache.put(element);
		}else{
			logger.debug("get result from cache");
		}
		return element.getValue();
	}

	/**
	 * creates cache key: targetName.methodName.argument0.argument1...
	 */
	private String getCacheKey(String targetName, String methodName, Object[] arguments) {
		StringBuffer sb = new StringBuffer();
		sb.append(targetName).append(".").append(methodName);
		if ((arguments != null) && (arguments.length != 0)) {
			for (int i = 0; i < arguments.length; i++) {
				sb.append(".").append(arguments[i]);
			}
		}

		return sb.toString();
	}
}


---------------------------------------------------------------------------------------------------------------------------------------

方法执行后的拦截器MethodCacheAfterAdvice.java:
package ehcache;

import java.lang.reflect.Method;  
import java.util.List;  
import net.sf.ehcache.Cache;    
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.springframework.aop.AfterReturningAdvice;  
import org.springframework.beans.factory.InitializingBean;  
import org.springframework.util.Assert;  
  
public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean  
{  
    private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);  
  
    private Cache cache;  
  
    public void setCache(Cache cache) {  
        this.cache = cache;  
    }  
  
    public MethodCacheAfterAdvice() {  
        super();  
    }  
  
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {  
        String className = arg3.getClass().getName();  
        List list = cache.getKeys();  
        for(int i = 0;i<list.size();i++){  
            String cacheKey = String.valueOf(list.get(i));  
            if(cacheKey.startsWith(className)){  
                cache.remove(cacheKey);  
                logger.debug("remove cache " + cacheKey);  
            }  
        }  
    }  
  
    public void afterPropertiesSet() throws Exception {  
        Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");  
    }    
}  


---------------------------------------------------------------------------------------------------------------------------------------

测试用的测试方法TestService.java:
package ehcache;

public class TestService{
	public String testMethod(){
		System.out.println("没走缓存,直接调用TestService.testMethod()");
		return "1";
	}
	
	public void updateMethod(){
		System.out.println("updateMethod");
	}
	
	public void insertMethod(){
		System.out.println("insertMethod");
	}
	
	public void deleteMethod(){
		System.out.println("deleteMethod");
	}	
}


---------------------------------------------------------------------------------------------------------------------------------------

缓存配置文件ehcache.xml:

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskSpoolBufferSizeMB="30"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
    <cache name="testCache"
      maxElementsInMemory="1000"
      eternal="false"
      timeToIdleSeconds="150"
      timeToLiveSeconds="150"
      overflowToDisk="false"
      memoryStoreEvictionPolicy="LRU"
    />


缓存配置文件ehcache-config.xml
<beans>
	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
	  <property name="configLocation">
	    <value>src/ehcache/ehcache.xml</value>
	  </property>
	</bean>

	<bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
		<property name="cacheManager">
			<ref local="cacheManager"/>
		</property>
		<property name="cacheName">
			<value>testCache</value>
		</property>
	</bean>
	
	<!-- 创建cache拦截器 -->
	<bean id="methodCacheInterceptor" class="ehcache.MethodCacheInterceptor">
	  <property name="cache">
	    <ref local="methodCache" />
	  </property>
	</bean>
	
	<!-- 销毁cache拦截器 -->
	<bean id="methodCacheAfterAdvice" class="ehcache.MethodCacheAfterAdvice">  
       <property name="cache">  
         <ref local="methodCache" />  
       </property>  
    </bean>  
	
	<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
	  <property name="advice">
	    <ref local="methodCacheInterceptor"/>
	  </property>
	  <property name="patterns">
	    <list>
	      <value>.*TestService.testMethod</value>
	     </list>
	  </property>
	</bean>
	
	<bean id="methodCacheDestory" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
	  <property name="advice">
	    <ref local="methodCacheAfterAdvice"/>
	  </property>
	  <property name="patterns">
	    <list>
	      <value>.*TestService.update*</value>
	      <value>.*TestService.insert*</value>
	      <value>.*TestService.delete*</value>
	     </list>
	  </property>
	</bean>
</beans> 


---------------------------------------------------------------------------------------------------------------------------------------

Spring配置文件applicationContext.xml
<beans default-autowire="byName">
	<import resource="ehcache-config.xml"/>
	<bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean" >
		<property name="target">
			<bean class="ehcache.TestService"/>
		</property>
		<property name="interceptorNames">
			<list>
				<value>methodCachePointCut</value>
				<value>methodCacheDestory</value>
			</list>
		</property>
	</bean>	
</beans>


---------------------------------------------------------------------------------------------------------------------------------------

测试用Main方法:
package ehcache;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class TestMain {

public static void main(String args[]) throws Exception{
		
        ApplicationContext ctx = new FileSystemXmlApplicationContext("src/ehcache/applicationContext.xml");   
        
        TestService t = (TestService)ctx.getBean("testService");
        
        System.out.println("第一次调用:" + t.testMethod());
        
        System.out.println("第二次调用:" + t.testMethod());
        
        System.out.print("更新操作:");
        
        t.updateMethod();
        
        System.out.println("第三次调用:" + t.testMethod());        
    }	
}


---------------------------------------------------------------------------------------------------------------------------------------
运行结果:
没走缓存,直接调用TestService.testMethod()
第一次调用:1
第二次调用:1
更新操作:updateMethod
没走缓存,直接调用TestService.testMethod()
第三次调用:1


可以看到,第一次调用时没走缓存,第二次就走缓存
然后执行update操作,执行完后销毁缓存
第三次调用,又没走缓存。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics