• Spring + EHcache配置


    需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系统中Service或则DAO层的get/find等方法返回结果,如果数据更新(使用Create/update/delete方法),则刷新cache中相应的内容。 

    根据需求,计划使用Spring AOP + ehCache来实现这个功能,采用ehCache原因之一是Spring提供了ehCache的支持,至于为何仅仅支持ehCache而不支持osCache和JBossCache无从得知(Hibernate???),但毕竟Spring提供了支持,可以减少一部分工作量:)。二是后来实现了OSCache和JBoss Cache的方式后,经过简单测试发现几个Cache在效率上没有太大的区别(不考虑集群),决定采用ehCahce。 

    AOP嘛,少不了拦截器,先创建一个实现了MethodInterceptor接口的拦截器,用来拦截Service/DAO的方法调用,拦截到方法后,搜索该方法的结果在cache中是否存在,如果存在,返回cache中的缓存结果,如果不存在,返回查询数据库的结果,并将结果缓存到cache中。 

    MethodCacheInterceptor.java

    Java代码 复制代码
    1. package com.co.cache.ehcache;   
    2.   
    3. import java.io.Serializable;   
    4.   
    5. import net.sf.ehcache.Cache;   
    6. import net.sf.ehcache.Element;   
    7.   
    8. import org.aopalliance.intercept.MethodInterceptor;   
    9. import org.aopalliance.intercept.MethodInvocation;   
    10. import org.apache.commons.logging.Log;   
    11. import org.apache.commons.logging.LogFactory;   
    12. import org.springframework.beans.factory.InitializingBean;   
    13. import org.springframework.util.Assert;   
    14.   
    15. public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean   
    16. {   
    17.     private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);   
    18.   
    19.     private Cache cache;   
    20.   
    21.     public void setCache(Cache cache) {   
    22.         this.cache = cache;   
    23.     }   
    24.   
    25.     public MethodCacheInterceptor() {   
    26.         super();   
    27.     }   
    28.   
    29.     /**  
    30.      * 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值,  
    31.      * 否则,返回数据库查询结果,并将查询结果放入cache  
    32.      */  
    33.     public Object invoke(MethodInvocation invocation) throws Throwable {   
    34.         String targetName = invocation.getThis().getClass().getName();   
    35.         String methodName = invocation.getMethod().getName();   
    36.         Object[] arguments = invocation.getArguments();   
    37.         Object result;   
    38.        
    39.         logger.debug("Find object from cache is " + cache.getName());   
    40.            
    41.         String cacheKey = getCacheKey(targetName, methodName, arguments);   
    42.         Element element = cache.get(cacheKey);   
    43.   
    44.         if (element == null) {   
    45.             logger.debug("Hold up method , Get method result and create cache........!");   
    46.             result = invocation.proceed();   
    47.             element = new Element(cacheKey, (Serializable) result);   
    48.             cache.put(element);   
    49.         }   
    50.         return element.getValue();   
    51.     }   
    52.   
    53.     /**  
    54.      * 获得cache key的方法,cache key是Cache中一个Element的唯一标识  
    55.      * cache key包括 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser  
    56.      */  
    57.     private String getCacheKey(String targetName, String methodName, Object[] arguments) {   
    58.         StringBuffer sb = new StringBuffer();   
    59.         sb.append(targetName).append(".").append(methodName);   
    60.         if ((arguments != null) && (arguments.length != 0)) {   
    61.             for (int i = 0; i < arguments.length; i++) {   
    62.                 sb.append(".").append(arguments[i]);   
    63.             }   
    64.         }   
    65.         return sb.toString();   
    66.     }   
    67.        
    68.     /**  
    69.      * implement InitializingBean,检查cache是否为空  
    70.      */  
    71.     public void afterPropertiesSet() throws Exception {   
    72.         Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");   
    73.     }   
    74.   
    75. }  
    [java] view plaincopy
    1. package com.co.cache.ehcache;  
    2.   
    3. import java.io.Serializable;  
    4.   
    5. import net.sf.ehcache.Cache;  
    6. import net.sf.ehcache.Element;  
    7.   
    8. import org.aopalliance.intercept.MethodInterceptor;  
    9. import org.aopalliance.intercept.MethodInvocation;  
    10. import org.apache.commons.logging.Log;  
    11. import org.apache.commons.logging.LogFactory;  
    12. import org.springframework.beans.factory.InitializingBean;  
    13. import org.springframework.util.Assert;  
    14.   
    15. public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean  
    16. {  
    17.     private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);  
    18.   
    19.     private Cache cache;  
    20.   
    21.     public void setCache(Cache cache) {  
    22.         this.cache = cache;  
    23.     }  
    24.   
    25.     public MethodCacheInterceptor() {  
    26.         super();  
    27.     }  
    28.   
    29.     /** 
    30.      * 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值, 
    31.      * 否则,返回数据库查询结果,并将查询结果放入cache 
    32.      */  
    33.     public Object invoke(MethodInvocation invocation) throws Throwable {  
    34.         String targetName = invocation.getThis().getClass().getName();  
    35.         String methodName = invocation.getMethod().getName();  
    36.         Object[] arguments = invocation.getArguments();  
    37.         Object result;  
    38.       
    39.         logger.debug("Find object from cache is " + cache.getName());  
    40.           
    41.         String cacheKey = getCacheKey(targetName, methodName, arguments);  
    42.         Element element = cache.get(cacheKey);  
    43.   
    44.         if (element == null) {  
    45.             logger.debug("Hold up method , Get method result and create cache........!");  
    46.             result = invocation.proceed();  
    47.             element = new Element(cacheKey, (Serializable) result);  
    48.             cache.put(element);  
    49.         }  
    50.         return element.getValue();  
    51.     }  
    52.   
    53.     /** 
    54.      * 获得cache key的方法,cache key是Cache中一个Element的唯一标识 
    55.      * cache key包括 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser 
    56.      */  
    57.     private String getCacheKey(String targetName, String methodName, Object[] arguments) {  
    58.         StringBuffer sb = new StringBuffer();  
    59.         sb.append(targetName).append(".").append(methodName);  
    60.         if ((arguments != null) && (arguments.length != 0)) {  
    61.             for (int i = 0; i < arguments.length; i++) {  
    62.                 sb.append(".").append(arguments[i]);  
    63.             }  
    64.         }  
    65.         return sb.toString();  
    66.     }  
    67.       
    68.     /** 
    69.      * implement InitializingBean,检查cache是否为空 
    70.      */  
    71.     public void afterPropertiesSet() throws Exception {  
    72.         Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");  
    73.     }  
    74.   
    75. }  



    上面的代码中可以看到,在方法public Object invoke(MethodInvocation invocation) 中,完成了搜索Cache/新建cache的功能。

    Java代码 复制代码
    1. Element element = cache.get(cacheKey);  
    [java] view plaincopy
    1. Element element = cache.get(cacheKey);  


    这句代码的作用是获取cache中的element,如果cacheKey所对应的element不存在,将会返回一个null值

    Java代码 复制代码
    1. result = invocation.proceed();  
    [java] view plaincopy
    1. result = invocation.proceed();  


    这句代码的作用是获取所拦截方法的返回值,详细请查阅AOP相关文档。 

    随后,再建立一个拦截器MethodCacheAfterAdvice,作用是在用户进行create/update/delete操作时来刷新/remove相关cache内容,这个拦截器实现了AfterReturningAdvice接口,将会在所拦截的方法执行后执行在public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3)方法中所预定的操作

    Java代码 复制代码
    1. package com.co.cache.ehcache;   
    2.   
    3. import java.lang.reflect.Method;   
    4. import java.util.List;   
    5.   
    6. import net.sf.ehcache.Cache;   
    7.   
    8. import org.apache.commons.logging.Log;   
    9. import org.apache.commons.logging.LogFactory;   
    10. import org.springframework.aop.AfterReturningAdvice;   
    11. import org.springframework.beans.factory.InitializingBean;   
    12. import org.springframework.util.Assert;   
    13.   
    14. public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean   
    15. {   
    16.     private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);   
    17.   
    18.     private Cache cache;   
    19.   
    20.     public void setCache(Cache cache) {   
    21.         this.cache = cache;   
    22.     }   
    23.   
    24.     public MethodCacheAfterAdvice() {   
    25.         super();   
    26.     }   
    27.   
    28.     public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {   
    29.         String className = arg3.getClass().getName();   
    30.         List list = cache.getKeys();   
    31.         for(int i = 0;i<list.size();i++){   
    32.             String cacheKey = String.valueOf(list.get(i));   
    33.             if(cacheKey.startsWith(className)){   
    34.                 cache.remove(cacheKey);   
    35.                 logger.debug("remove cache " + cacheKey);   
    36.             }   
    37.         }   
    38.     }   
    39.   
    40.     public void afterPropertiesSet() throws Exception {   
    41.         Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");   
    42.     }   
    43.   
    44. }  
    [java] view plaincopy
    1. package com.co.cache.ehcache;  
    2.   
    3. import java.lang.reflect.Method;  
    4. import java.util.List;  
    5.   
    6. import net.sf.ehcache.Cache;  
    7.   
    8. import org.apache.commons.logging.Log;  
    9. import org.apache.commons.logging.LogFactory;  
    10. import org.springframework.aop.AfterReturningAdvice;  
    11. import org.springframework.beans.factory.InitializingBean;  
    12. import org.springframework.util.Assert;  
    13.   
    14. public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean  
    15. {  
    16.     private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);  
    17.   
    18.     private Cache cache;  
    19.   
    20.     public void setCache(Cache cache) {  
    21.         this.cache = cache;  
    22.     }  
    23.   
    24.     public MethodCacheAfterAdvice() {  
    25.         super();  
    26.     }  
    27.   
    28.     public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {  
    29.         String className = arg3.getClass().getName();  
    30.         List list = cache.getKeys();  
    31.         for(int i = 0;i<list.size();i++){  
    32.             String cacheKey = String.valueOf(list.get(i));  
    33.             if(cacheKey.startsWith(className)){  
    34.                 cache.remove(cacheKey);  
    35.                 logger.debug("remove cache " + cacheKey);  
    36.             }  
    37.         }  
    38.     }  
    39.   
    40.     public void afterPropertiesSet() throws Exception {  
    41.         Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");  
    42.     }  
    43.   
    44. }  


    上面的代码很简单,实现了afterReturning方法实现自AfterReturningAdvice接口,方法中所定义的内容将会在目标方法执行后执行,在该方法中

    Java代码 复制代码
    1. String className = arg3.getClass().getName();  
    [java] view plaincopy
    1. String className = arg3.getClass().getName();  

    的作用是获取目标class的全名,如:com.co.cache.test.TestServiceImpl,然后循环cache的key list,remove cache中所有和该class相关的element。 

    随后,开始配置ehCache的属性,ehCache需要一个xml文件来设置ehCache相关的一些属性,如最大缓存数量、cache刷新的时间等等. 
    ehcache.xml

    Java代码 复制代码
    1. <ehcache>   
    2.     <diskStore path="c://myapp//cache"/>   
    3.     <defaultCache   
    4.         maxElementsInMemory="1000"  
    5.         eternal="false"  
    6.         timeToIdleSeconds="120"  
    7.         timeToLiveSeconds="120"  
    8.         overflowToDisk="true"  
    9.         />   
    10.   <cache name="DEFAULT_CACHE"  
    11.         maxElementsInMemory="10000"  
    12.         eternal="false"  
    13.         timeToIdleSeconds="300000"  
    14.         timeToLiveSeconds="600000"  
    15.         overflowToDisk="true"  
    16.         />   
    17. </ehcache>  
    [java] view plaincopy
    1. <ehcache>  
    2.     <diskStore path="c://myapp//cache"/>  
    3.     <defaultCache  
    4.         maxElementsInMemory="1000"  
    5.         eternal="false"  
    6.         timeToIdleSeconds="120"  
    7.         timeToLiveSeconds="120"  
    8.         overflowToDisk="true"  
    9.         />  
    10.   <cache name="DEFAULT_CACHE"  
    11.         maxElementsInMemory="10000"  
    12.         eternal="false"  
    13.         timeToIdleSeconds="300000"  
    14.         timeToLiveSeconds="600000"  
    15.         overflowToDisk="true"  
    16.         />  
    17. </ehcache>  


    配置每一项的详细作用不再详细解释,有兴趣的请google下 ,这里需要注意一点defaultCache标签定义了一个默认的Cache,这个Cache是不能删除的,否则会抛出No default cache is configured异常。另外,由于使用拦截器来刷新Cache内容,因此在定义cache生命周期时可以定义较大的数值,timeToIdleSeconds="300000" timeToLiveSeconds="600000",好像还不够大? 

    然后,在将Cache和两个拦截器配置到Spring,这里没有使用2.0里面AOP的标签。 
    cacheContext.xml

    Java代码 复制代码
    1. <?xml version="1.0" encoding="UTF-8"?>   
    2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">   
    3. <beans>   
    4.     <!-- 引用ehCache的配置 -->   
    5.     <bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">   
    6.       <property name="configLocation">   
    7.         <value>ehcache.xml</value>   
    8.       </property>   
    9.     </bean>   
    10.        
    11.     <!-- 定义ehCache的工厂,并设置所使用的Cache name -->   
    12.     <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">   
    13.       <property name="cacheManager">   
    14.         <ref local="defaultCacheManager"/>   
    15.       </property>   
    16.       <property name="cacheName">   
    17.           <value>DEFAULT_CACHE</value>   
    18.       </property>   
    19.     </bean>   
    20.   
    21.     <!-- find/create cache拦截器 -->   
    22.     <bean id="methodCacheInterceptor" class="com.co.cache.ehcache.MethodCacheInterceptor">   
    23.       <property name="cache">   
    24.         <ref local="ehCache" />   
    25.       </property>   
    26.     </bean>   
    27.     <!-- flush cache拦截器 -->   
    28.     <bean id="methodCacheAfterAdvice" class="com.co.cache.ehcache.MethodCacheAfterAdvice">   
    29.       <property name="cache">   
    30.         <ref local="ehCache" />   
    31.       </property>   
    32.     </bean>   
    33.        
    34.     <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">   
    35.       <property name="advice">   
    36.         <ref local="methodCacheInterceptor"/>   
    37.       </property>   
    38.       <property name="patterns">   
    39.         <list>   
    40.             <value>.*find.*</value>   
    41.             <value>.*get.*</value>   
    42.         </list>   
    43.       </property>   
    44.     </bean>   
    45.     <bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">   
    46.       <property name="advice">   
    47.         <ref local="methodCacheAfterAdvice"/>   
    48.       </property>   
    49.       <property name="patterns">   
    50.         <list>   
    51.           <value>.*create.*</value>   
    52.           <value>.*update.*</value>   
    53.           <value>.*delete.*</value>   
    54.         </list>   
    55.       </property>   
    56.     </bean>   
    57. </beans>  
    [java] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
    3. <beans>  
    4.     <!-- 引用ehCache的配置 -->  
    5.     <bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
    6.       <property name="configLocation">  
    7.         <value>ehcache.xml</value>  
    8.       </property>  
    9.     </bean>  
    10.       
    11.     <!-- 定义ehCache的工厂,并设置所使用的Cache name -->  
    12.     <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
    13.       <property name="cacheManager">  
    14.         <ref local="defaultCacheManager"/>  
    15.       </property>  
    16.       <property name="cacheName">  
    17.           <value>DEFAULT_CACHE</value>  
    18.       </property>  
    19.     </bean>  
    20.   
    21.     <!-- find/create cache拦截器 -->  
    22.     <bean id="methodCacheInterceptor" class="com.co.cache.ehcache.MethodCacheInterceptor">  
    23.       <property name="cache">  
    24.         <ref local="ehCache" />  
    25.       </property>  
    26.     </bean>  
    27.     <!-- flush cache拦截器 -->  
    28.     <bean id="methodCacheAfterAdvice" class="com.co.cache.ehcache.MethodCacheAfterAdvice">  
    29.       <property name="cache">  
    30.         <ref local="ehCache" />  
    31.       </property>  
    32.     </bean>  
    33.       
    34.     <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
    35.       <property name="advice">  
    36.         <ref local="methodCacheInterceptor"/>  
    37.       </property>  
    38.       <property name="patterns">  
    39.         <list>  
    40.             <value>.*find.*</value>  
    41.             <value>.*get.*</value>  
    42.         </list>  
    43.       </property>  
    44.     </bean>  
    45.     <bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
    46.       <property name="advice">  
    47.         <ref local="methodCacheAfterAdvice"/>  
    48.       </property>  
    49.       <property name="patterns">  
    50.         <list>  
    51.           <value>.*create.*</value>  
    52.           <value>.*update.*</value>  
    53.           <value>.*delete.*</value>  
    54.         </list>  
    55.       </property>  
    56.     </bean>  
    57. </beans>  


    上面的代码最终创建了两个"切入点",methodCachePointCut和methodCachePointCutAdvice,分别用于拦截不同方法名的方法,可以根据需要任意增加所需要拦截方法的名称。 
    需要注意的是

    Java代码 复制代码
    1. <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">   
    2.       <property name="cacheManager">   
    3.         <ref local="defaultCacheManager"/>   
    4.       </property>   
    5.       <property name="cacheName">   
    6.           <value>DEFAULT_CACHE</value>   
    7.       </property>   
    8.     </bean>  
    [java] view plaincopy
    1. <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
    2.       <property name="cacheManager">  
    3.         <ref local="defaultCacheManager"/>  
    4.       </property>  
    5.       <property name="cacheName">  
    6.           <value>DEFAULT_CACHE</value>  
    7.       </property>  
    8.     </bean>  


    如果cacheName属性内设置的name在ehCache.xml中无法找到,那么将使用默认的cache(defaultCache标签定义). 

    事实上到了这里,一个简单的Spring + ehCache Framework基本完成了,为了测试效果,举一个实际应用的例子,定义一个TestService和它的实现类TestServiceImpl,里面包含 

    两个方法getAllObject()和updateObject(Object Object),具体代码如下 
    TestService.java

    Java代码 复制代码
    1. package com.co.cache.test;   
    2.   
    3. import java.util.List;   
    4.   
    5. public interface TestService {   
    6.     public List getAllObject();   
    7.   
    8.     public void updateObject(Object Object);   
    9. }  
    [java] view plaincopy
    1. package com.co.cache.test;  
    2.   
    3. import java.util.List;  
    4.   
    5. public interface TestService {  
    6.     public List getAllObject();  
    7.   
    8.     public void updateObject(Object Object);  
    9. }  



    TestServiceImpl.java

    Java代码 复制代码
    1. package com.co.cache.test;   
    2.   
    3. import java.util.List;   
    4.   
    5. public class TestServiceImpl implements TestService   
    6. {   
    7.     public List getAllObject() {   
    8.         System.out.println("---TestService:Cache内不存在该element,查找并放入Cache!");   
    9.         return null;   
    10.     }   
    11.   
    12.     public void updateObject(Object Object) {   
    13.         System.out.println("---TestService:更新了对象,这个Class产生的cache都将被remove!");   
    14.     }   
    15. }  
    [java] view plaincopy
    1. package com.co.cache.test;  
    2.   
    3. import java.util.List;  
    4.   
    5. public class TestServiceImpl implements TestService  
    6. {  
    7.     public List getAllObject() {  
    8.         System.out.println("---TestService:Cache内不存在该element,查找并放入Cache!");  
    9.         return null;  
    10.     }  
    11.   
    12.     public void updateObject(Object Object) {  
    13.         System.out.println("---TestService:更新了对象,这个Class产生的cache都将被remove!");  
    14.     }  
    15. }  


    使用Spring提供的AOP进行配置 
    applicationContext.xml

    Java代码 复制代码
    1. <?xml version="1.0" encoding="UTF-8"?>   
    2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">   
    3.   
    4. <beans>   
    5.     <import resource="cacheContext.xml"/>   
    6.        
    7.     <bean id="testServiceTarget" class="com.co.cache.test.TestServiceImpl"/>   
    8.        
    9.     <bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean">   
    10.       <property name="target">   
    11.           <ref local="testServiceTarget"/>   
    12.       </property>   
    13.       <property name="interceptorNames">   
    14.         <list>   
    15.           <value>methodCachePointCut</value>   
    16.           <value>methodCachePointCutAdvice</value>   
    17.         </list>   
    18.       </property>   
    19.     </bean>   
    20. </beans>  
    [java] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
    3.   
    4. <beans>  
    5.     <import resource="cacheContext.xml"/>  
    6.       
    7.     <bean id="testServiceTarget" class="com.co.cache.test.TestServiceImpl"/>  
    8.       
    9.     <bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean">  
    10.       <property name="target">  
    11.           <ref local="testServiceTarget"/>  
    12.       </property>  
    13.       <property name="interceptorNames">  
    14.         <list>  
    15.           <value>methodCachePointCut</value>  
    16.           <value>methodCachePointCutAdvice</value>  
    17.         </list>  
    18.       </property>  
    19.     </bean>  
    20. </beans>  


    这里一定不能忘记import cacheContext.xml文件,不然定义的两个拦截器就没办法使用了。 

    最后,写一个测试的代码 
    MainTest.java

    Java代码 复制代码
    1. package com.co.cache.test;   
    2.   
    3. import org.springframework.context.ApplicationContext;   
    4. import org.springframework.context.support.ClassPathXmlApplicationContext;   
    5.   
    6. public class MainTest{   
    7.     public static void main(String args[]){   
    8.         String DEFAULT_CONTEXT_FILE = "/applicationContext.xml";   
    9.         ApplicationContext context =  new ClassPathXmlApplicationContext(DEFAULT_CONTEXT_FILE);   
    10.         TestService testService = (TestService)context.getBean("testService");   
    11.   
    12.         System.out.println("1--第一次查找并创建cache");   
    13.         testService.getAllObject();   
    14.            
    15.         System.out.println("2--在cache中查找");   
    16.         testService.getAllObject();   
    17.            
    18.         System.out.println("3--remove cache");   
    19.         testService.updateObject(null);   
    20.            
    21.         System.out.println("4--需要重新查找并创建cache");   
    22.         testService.getAllObject();   
    23.     }      
    24. }  
    [java] view plaincopy
    1. package com.co.cache.test;  
    2.   
    3. import org.springframework.context.ApplicationContext;  
    4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
    5.   
    6. public class MainTest{  
    7.     public static void main(String args[]){  
    8.         String DEFAULT_CONTEXT_FILE = "/applicationContext.xml";  
    9.         ApplicationContext context =  new ClassPathXmlApplicationContext(DEFAULT_CONTEXT_FILE);  
    10.         TestService testService = (TestService)context.getBean("testService");  
    11.   
    12.         System.out.println("1--第一次查找并创建cache");  
    13.         testService.getAllObject();  
    14.           
    15.         System.out.println("2--在cache中查找");  
    16.         testService.getAllObject();  
    17.           
    18.         System.out.println("3--remove cache");  
    19.         testService.updateObject(null);  
    20.           
    21.         System.out.println("4--需要重新查找并创建cache");  
    22.         testService.getAllObject();  
    23.     }     
    24. }  



    运行,结果如下

    Java代码 复制代码
    1. 1--第一次查找并创建cache   
    2. ---TestService:Cache内不存在该element,查找并放入Cache!   
    3. 2--在cache中查找   
    4. 3--remove cache   
    5. ---TestService:更新了对象,这个Class产生的cache都将被remove!   
    6. 4--需要重新查找并创建cache   
    7. ---TestService:Cache内不存在该element,查找并放入Cache!  
    [java] view plaincopy
    1. 1--第一次查找并创建cache  
    2. ---TestService:Cache内不存在该element,查找并放入Cache!  
    3. 2--在cache中查找  
    4. 3--remove cache  
    5. ---TestService:更新了对象,这个Class产生的cache都将被remove!  
    6. 4--需要重新查找并创建cache  
    7. ---TestService:Cache内不存在该element,查找并放入Cache!  



    大功告成 .可以看到,第一步执行getAllObject(),执行TestServiceImpl内的方法,并创建了cache,在第二次执行getAllObject()方法时,由于cache有该方法的缓存,直接从cache中get出方法的结果,所以没有打印出TestServiceImpl中的内容,而第三步,调用了updateObject方法,和TestServiceImpl相关的cache被remove,所以在第四步执行时,又执行TestServiceImpl中的方法,创建Cache。 

    网上也有不少类似的例子,但是很多都不是很完备,自己参考了一些例子的代码,其实在spring-modules中也提供了对几种cache的支持,ehCache,OSCache,JBossCache这些,看了一下,基本上都是采用类似的方式,只不过封装的更完善一些,主要思路也还是Spring的AOP,有兴趣的可以研究一下。

  • 相关阅读:
    第六次作业SSM
    第五次作业——MVC2项目实践
    第四次作业——JSP显示新闻
    第三次作业——servlet应用
    第二次作业——模仿登录页面
    第一次作业——Java web基础
    Alpha项目测试
    作业三
    第二次作业
    第一次阅读作业-201731062609-庞斌
  • 原文地址:https://www.cnblogs.com/daichangya/p/12958960.html
Copyright © 2020-2023  润新知