- 浏览: 49089 次
- 性别:
- 来自: 台源
最新评论
如果我们的项目中采用的是Spring+hibernate来构建的,在缓存方面,我们一定会首先想到Spring自带的EHCache缓存工具,在Spring中集成了目前比较流行的缓存策略EHCache,现在用的比较多的还有像OSCache,MemCached.这些应该是当前用的最多的缓存工具了。
在Spring+hibernate的这样的框架中,EHCache应该属于二级缓存了,我们知道在Hibernate中已经默认的使用了一级缓存,也就是在Session中。二级缓存应该是SessionFactory的范围了。二级缓存默认不会起作用的,这就需要我们简单的配置一下就可以了。
在配置之前,我先说明一点,缓存从理论上来说是可以提高你网站系统的性能,但前提就是你要保证你有一个良好的架构设计。比如用Spring+Hibernate构建的系统,如果用单个服务器,用Spring自带的EHCache来做二级缓存是再好不过了。如果你的系统是分布式的系统,有多台服务器,那么MemCached是最好的选择了,一般来说MemCached在做缓存这一块,要比EHCache和OSCache的性能要好点,但是并不是所有的网站用MemCached都能达到事半功倍的,它虽然是比较好,但它有一个前提,那就是你有多台服务器,是分布式的。这样用MemCached对系统的性能一定OK。因为Memcached是“分布式”的内存对象缓存系统,那么就是说,那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用, MemCached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源 .OSCache这个缓存机制的限制就比较少了。它和EHCache差不多。
在Spring+Hibernate中整合EHCache只需简单的三步。
第一步:配置缓存文件ehcache.xml,默认放到src目录下。下面是简单的配置。
上面有一个默认的缓存配置,还有一个我们自己配置的缓存,在应用程序中如果不指明缓存的话,就会默认的使用默认的配置属性。
第二步:用Spring中的强大机制,面向切面的设计AOP.来编写两个类文件,MethodCacheAfterAdvice.java(主要是对脏东西的同步更新)和MethodCacheInterceptor.java(主要使用拦截器来为要缓存的对象建立缓存并缓存)。拦截器的实现机制其实就是我们常用的过滤器。它和过滤器的工作原理一样。以下是这两个文件。
MethodCacheInterceptor.java
这个方法实现了两个接口,一个是MethodInterceptor(方法拦截),它主要是在方法的调用前后都可以执行。另一个InitializingBean (初始化Bean)它主要在方法调用之后做一下简单的检查,主要实现写在afterPropertiesSet()中,就可以了 。
MethodCacheAfterAdvice .java
这个方法主要是保证缓存的同步,保持与数据库的数据一致性。
第三步:配置Bean了,applicationContext-ehcache.xml文件就是Spring中的Ioc(控制反转容器)的描述了。上面的只是简单的写了两个方法,具体的能起到什么作用,以及何时起作用,以及怎样用声明式的方式(AOP)和Bean结合。
上面我是针对DAO层进行拦截并缓存的,最好是能在业务层进行拦截会更好,你可以根据你的系统具体的设计,如果没有业务层的话,对DAO层拦截也是可以的。拦截采用的是用正规表达式配置的。对find,get的方法只进行缓存,如果 create,update,delete方法进行缓存的同步。对一些频繁的操作最好不要用缓存,缓存的作用就是针对那些不经常变动的操作。
只需这简单的三部就可以完成EHCache了。最好亲自试一试。我并没有针对里面对方法过细的讲解。其实都很简单,多看看就会明白了。不当之处,敬请原谅。
上文出自 “魏杰的技术专栏” 博客,请务必保留此出处
附:ehcache配置文件内容详解:
maxElementsInMemory :cache 中最多可以存放的元素的数量。如果放入cache中的元素超过这个数值,有两种情况:
1. 若overflowToDisk的属性值为true,会将cache中多出的元素放入磁盘文件中。
2. 若overflowToDisk的属性值为false,会根据memoryStoreEvictionPolicy的策略替换cache中原有的元素。
eternal :是否永驻内存。如果值是true,cache中的元素将一直保存在内存中,不会因为时间超时而丢失,所以在这个值为true的时候,timeToIdleSeconds和timeToLiveSeconds两个属性的值就不起作用了。
3. timeToIdleSeconds :访问这个cache中元素的最大间隔时间。如果超过这个时间没有访问这个cache中的某个元素,那么这个元素将被从cache中清除。
4. timeToLiveSeconds : cache中元素的生存时间。意思是从cache中的某个元素从创建到消亡的时间,从创建开始计时,当超过这个时间,这个元素将被从cache中清除。
5. overflowToDisk :溢出是否写入磁盘。系统会根据标签<diskStore path="java.io.tmpdir"/> 中path的值查找对应的属性值,如果系统的java.io.tmpdir的值是 D:\temp,写入磁盘的文件就会放在这个文件夹下。文件的名称是cache的名称,后缀名的data。如:CACHE_FUNC.data。
6. diskExpiryThreadIntervalSeconds :磁盘缓存的清理线程运行间隔.
7. memoryStoreEvictionPolicy :内存存储与释放策略。有三个值:
LRU -least recently used
LFU -least frequently used
FIFO-first in first out, the oldest element by creation time
diskPersistent : 是否持久化磁盘缓存。当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称,后缀名为index的的文件,如 CACHE_FUNC.index 。这个文件中存放了已经持久化在磁盘中的cache的index,找到后把cache加载到内存。要想把cache真正持久化到磁盘,写程序时必须注意,在是用net.sf.ehcache.Cache的void put (Element element)方法后要使用void flush()方法。
更多说明可看ehcache自带的ehcache.xml的注释说明.
在Spring+hibernate的这样的框架中,EHCache应该属于二级缓存了,我们知道在Hibernate中已经默认的使用了一级缓存,也就是在Session中。二级缓存应该是SessionFactory的范围了。二级缓存默认不会起作用的,这就需要我们简单的配置一下就可以了。
在配置之前,我先说明一点,缓存从理论上来说是可以提高你网站系统的性能,但前提就是你要保证你有一个良好的架构设计。比如用Spring+Hibernate构建的系统,如果用单个服务器,用Spring自带的EHCache来做二级缓存是再好不过了。如果你的系统是分布式的系统,有多台服务器,那么MemCached是最好的选择了,一般来说MemCached在做缓存这一块,要比EHCache和OSCache的性能要好点,但是并不是所有的网站用MemCached都能达到事半功倍的,它虽然是比较好,但它有一个前提,那就是你有多台服务器,是分布式的。这样用MemCached对系统的性能一定OK。因为Memcached是“分布式”的内存对象缓存系统,那么就是说,那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用, MemCached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源 .OSCache这个缓存机制的限制就比较少了。它和EHCache差不多。
在Spring+Hibernate中整合EHCache只需简单的三步。
第一步:配置缓存文件ehcache.xml,默认放到src目录下。下面是简单的配置。
<ehcache> <!—设置缓存文件 .data 的创建路径。 如果该路径是 Java 系统参数,当前虚拟机会重新赋值。 下面的参数这样解释: user.home – 用户主目录 user.dir – 用户当前工作目录 java.io.tmpdir – 默认临时文件路径,就是在tomcat的temp目录 --> <diskStore path="java.io.tmpdir"/> <!—缺省缓存配置。CacheManager 会把这些配置应用到程序中。 下列属性是 defaultCache 必须的: maxInMemory - 设定内存中创建对象的最大值。 eternal - 设置元素(译注:内存中对象)是否永久驻留。 如果是,将忽略超时限制且元素永不消亡。 timeToIdleSeconds - 设置某个元素消亡前的停顿时间。 也就是在一个元素消亡之前,两次访问时间的最大时间间隔值。 这只能在元素不是永久驻留时有效(译注:如果对象永恒不灭,则 设置该属性也无用)。 如果该值是 0 就意味着元素可以停顿无穷长的时间。 timeToLiveSeconds - 为元素设置消亡前的生存时间。 也就是一个元素从构建到消亡的最大时间间隔值。 这只能在元素不是永久驻留时有效。 overflowToDisk - 设置当内存中缓存达到 maxInMemory 限制时元素是否可写到磁盘上。 --> <!--timeToLiveSeconds的时间一定要大于等于timeToIdleSeconds的时间按--> <cache name="DEFAULT_CACHE" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="500" timeToLiveSeconds="500" overflowToDisk="true" /> </ehcache>
上面有一个默认的缓存配置,还有一个我们自己配置的缓存,在应用程序中如果不指明缓存的话,就会默认的使用默认的配置属性。
第二步:用Spring中的强大机制,面向切面的设计AOP.来编写两个类文件,MethodCacheAfterAdvice.java(主要是对脏东西的同步更新)和MethodCacheInterceptor.java(主要使用拦截器来为要缓存的对象建立缓存并缓存)。拦截器的实现机制其实就是我们常用的过滤器。它和过滤器的工作原理一样。以下是这两个文件。
MethodCacheInterceptor.java
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 MethodCacheInterceptor() { super(); } /** * 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值, 否则,返回数据库查询结果,并将查询结果放入cache */ 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("Find object from cache is " + cache.getName()); String cacheKey = getCacheKey(targetName, methodName, arguments); Element element = cache.get(cacheKey); long startTime = System.currentTimeMillis(); if (element == null) { logger.debug("Hold up method , Get method result and create cache........!"); result = invocation.proceed(); element = new Element(cacheKey, (Serializable) result); cache.put(element); long endTime = System.currentTimeMillis(); logger.info(targetName + "." + methodName + " 方法被首次调用并被缓存。耗时" + (endTime - startTime) + "毫秒" + " cacheKey:" + element.getKey()); } else { long endTime = System.currentTimeMillis(); logger.info(targetName + "." + methodName + " 结果从缓存中直接调用。耗时" + (endTime - startTime) + "毫秒" + " cacheKey:" + element.getKey()); } return element.getValue(); } /** * 获得cache key的方法,cache key是Cache中一个Element的唯一标识 cache key包括 包名+类名+方法名+参数 */ 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(); } /** * implement InitializingBean,检查cache是否为空 */ public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it."); } }
这个方法实现了两个接口,一个是MethodInterceptor(方法拦截),它主要是在方法的调用前后都可以执行。另一个InitializingBean (初始化Bean)它主要在方法调用之后做一下简单的检查,主要实现写在afterPropertiesSet()中,就可以了 。
MethodCacheAfterAdvice .java
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."); } }
这个方法主要是保证缓存的同步,保持与数据库的数据一致性。
第三步:配置Bean了,applicationContext-ehcache.xml文件就是Spring中的Ioc(控制反转容器)的描述了。上面的只是简单的写了两个方法,具体的能起到什么作用,以及何时起作用,以及怎样用声明式的方式(AOP)和Bean结合。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="[url]http://www.springframework.org/schema/beans[/url]" xmlns:xsi="[url]http://www.w3.org/2001/XMLSchema-instance[/url]" xsi:schemaLocation="[url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]"> <!-- 利用BeanNameAutoProxyCreator自动创建事务代理 --> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- 引用ehCache的配置 --> <bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation"> <value>classpath:ehcache.xml</value> </property> </bean> <!-- 定义ehCache的工厂,并设置所使用的Cache name --> <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref local="defaultCacheManager" /> </property> <property name="cacheName"> <value>DEFAULT_CACHE</value> </property> </bean> <!-- find/create cache拦截器 --> <bean id="methodCacheInterceptor" class="com.w3cs.cache.ehcache.MethodCacheInterceptor"> <property name="cache"> <ref local="ehCache" /> </property> </bean> <!-- flush cache拦截器 --> <bean id="methodCacheAfterAdvice" class="com.w3cs.cache.ehcache.MethodCacheAfterAdvice"> <property name="cache"> <ref local="ehCache" /> </property> </bean> <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="methodCacheInterceptor" /> </property> <property name="patterns"> <list> <value>.*find.*</value> <value>.*get.*</value> </list> </property> </bean> <bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="methodCacheAfterAdvice" /> </property> <property name="patterns"> <list> <value>.*create.*</value> <value>.*update.*</value> <value>.*delete.*</value> </list> </property> </bean> <!-- 自动代理 --> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- 可以是Service或DAO层(最好是针对业务层*Service) --> <property name="beanNames"> <list> <value>*DAO</value> </list> </property> <property name="interceptorNames"> <list> <value>methodCachePointCut</value> <value>methodCachePointCutAdvice</value> <value>transactionInterceptor</value> </list> </property> </bean> </beans>
上面我是针对DAO层进行拦截并缓存的,最好是能在业务层进行拦截会更好,你可以根据你的系统具体的设计,如果没有业务层的话,对DAO层拦截也是可以的。拦截采用的是用正规表达式配置的。对find,get的方法只进行缓存,如果 create,update,delete方法进行缓存的同步。对一些频繁的操作最好不要用缓存,缓存的作用就是针对那些不经常变动的操作。
只需这简单的三部就可以完成EHCache了。最好亲自试一试。我并没有针对里面对方法过细的讲解。其实都很简单,多看看就会明白了。不当之处,敬请原谅。
上文出自 “魏杰的技术专栏” 博客,请务必保留此出处
附:ehcache配置文件内容详解:
maxElementsInMemory :cache 中最多可以存放的元素的数量。如果放入cache中的元素超过这个数值,有两种情况:
1. 若overflowToDisk的属性值为true,会将cache中多出的元素放入磁盘文件中。
2. 若overflowToDisk的属性值为false,会根据memoryStoreEvictionPolicy的策略替换cache中原有的元素。
eternal :是否永驻内存。如果值是true,cache中的元素将一直保存在内存中,不会因为时间超时而丢失,所以在这个值为true的时候,timeToIdleSeconds和timeToLiveSeconds两个属性的值就不起作用了。
3. timeToIdleSeconds :访问这个cache中元素的最大间隔时间。如果超过这个时间没有访问这个cache中的某个元素,那么这个元素将被从cache中清除。
4. timeToLiveSeconds : cache中元素的生存时间。意思是从cache中的某个元素从创建到消亡的时间,从创建开始计时,当超过这个时间,这个元素将被从cache中清除。
5. overflowToDisk :溢出是否写入磁盘。系统会根据标签<diskStore path="java.io.tmpdir"/> 中path的值查找对应的属性值,如果系统的java.io.tmpdir的值是 D:\temp,写入磁盘的文件就会放在这个文件夹下。文件的名称是cache的名称,后缀名的data。如:CACHE_FUNC.data。
6. diskExpiryThreadIntervalSeconds :磁盘缓存的清理线程运行间隔.
7. memoryStoreEvictionPolicy :内存存储与释放策略。有三个值:
LRU -least recently used
LFU -least frequently used
FIFO-first in first out, the oldest element by creation time
diskPersistent : 是否持久化磁盘缓存。当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称,后缀名为index的的文件,如 CACHE_FUNC.index 。这个文件中存放了已经持久化在磁盘中的cache的index,找到后把cache加载到内存。要想把cache真正持久化到磁盘,写程序时必须注意,在是用net.sf.ehcache.Cache的void put (Element element)方法后要使用void flush()方法。
更多说明可看ehcache自带的ehcache.xml的注释说明.
发表评论
-
WSDL中min0ccurs和nillable的区别
2011-08-15 16:59 8139minOccurs="0" 在null的时 ... -
[转]Hibernate的proxool连接池参数
2010-05-20 18:05 1181Example configuration: <p ... -
[转]Spring几种获取Bean的方式
2010-05-20 08:34 1279获得spring里注册Bean的四种方法,特别是第三种方法,简 ... -
[转]Spring中ApplicationContext的获取方式
2010-05-20 08:29 933Spring中ApplicationContext加载机制。 ... -
[转]Struts 2.1.x + Spring 2.5.x + Hibernate 3.3.x整合需要的JAR包
2010-05-19 08:55 1254下面这个表相信对很多人都有用: jar包名称 ... -
Spring整合Hibernate
2010-05-18 22:39 0Hibernate3.3 + Spring2.5整合 1.包 ... -
[转]Javascript解析XML文档
2010-05-11 15:41 730例如有如下XML文件: <?xml version ... -
[转]Criteria和DetachedCriteria的分别
2010-05-07 12:42 778使用 Spring 和 Hibernate 进行开发,有 ... -
Java读取properties文件的思考
2010-04-21 15:33 1120此文为转载,原文地址:http://lavasoft.blog ... -
超简单的QuartZ上手入门教程
2010-04-19 16:57 2282随便写个Job类,实现quartz的job package ... -
MAS系统的ApiClient源码
2010-03-23 10:12 3818此文为转载,权作参考! package com.jasson ... -
LRC格式转换
2008-09-12 23:36 1305import java.io.BufferedReader; ...
相关推荐
NULL 博文链接:https://java-script.iteye.com/blog/1160745
NULL 博文链接:https://topmanopensource.iteye.com/blog/752946
NULL 博文链接:https://honda418.iteye.com/blog/354945
基于公司的项目在Spring中集成Ehcache,并提供EhcaheUtils工具类,并通过Spring的AOP编程实现方法缓存注解话,先奉献出核心代码,需要的朋友可以参考哦!
support模块和SpEL(Spring Expression Language,Spring表达式语言)模块组成,具体介绍如下: Beans模块:提供了BeanFactory,是工厂模式的经典实现,Spring将管理对象称为Bean。 Core核心模块:提供了Spring框架...
缘起需求:需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系统中Service或者DAO层的get/find等方法返回结果,如果数据更新(使用Create/update/...
本代码通过使用spring aop+ehcache的技术,实现了方法级别的查询缓存,主要原理是 方法的完整路径+方法参数值,作为key,放入cache中,下次访问时先判断cache中是否有该key.
NULL 博文链接:https://topmanopensource.iteye.com/blog/752948
1.标题所提及技术的整合,Spring包括mvc、aop、ioc等。个人属于强迫症类型,技术水平怎么样再说,代码必须好看 2.Hibernate几个级别缓存对比。见DaoImpl类 3.Ehcache方法缓存及页面缓存。见applicationContext-cache...
使用Spring AOP技术 + ehcache做的一个缓存。此代码为转载,供大家学习使用。
【EhCache】Java缓存框架使用EhCache结合Spring AOP EhCache是一个纯Java的进程内缓存框架,具有如下特点: 1. 快速简单,非常容易和应用集成。 2.支持多种缓存策略 。 3. 缓存数据有两级:内存和磁盘,因此无需...
Aspect Cache是一个针对Spring Boot,基于AOP注解方式的轻量级缓存,目前支持EHCache,Redis缓存方式。数据类型支持POJO、Map和List数据类型,同时支持自定义缓存key解析,也支持自定义的缓存处理方式,或者扩展支持...
ehcache需要的jar包,配合spring的aop使用,很不错哦
1.标题所提及技术的整合,Spring包括mvc、aop、ioc等。个人属于强迫症类型,技术水平怎么样再说,代码必须好看 2.Hibernate几个级别缓存对比。见DaoImpl类 3.Ehcache方法缓存及页面缓存。见applicationContext-cache...
Spring Cloud Config统一配置管理 使用Spring Cloud Bus刷新配置 使用Spring Cloud Sleuth跟踪微服务 Spring Cloud Consul服务治理 五、Spring Boot && Dubbo教程 Spring Boot整合Dubbo&Zookeeper; 监控Dubbo服务 ...
(2) spring-beans.jar 这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI支持,...
- Spring 缓存,包括redis、ehcache、spring-cache、memcached、使用redis实现session共享 等。 - spring-docs - Spring 文档生成工具,包括 Swagger - spring-bussiness - Spring 业务应用,包括 AOP、过滤...
spring中使用缓存的方案,根据需求,使用Spring AOP + ehCache可实现些功能,使用EHCACHE能方便地结合SPRING来实现缓存。