`
chxiaowu
  • 浏览: 240177 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

利用Spring的AOP来配置和管理你的二级缓存(EHCache)

 
阅读更多

如果我们的项目中采用的是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目录下。下面是简单的配置。

Xml代码
  1. < ehcache >   
  2.     <!—设置缓存文件 .data 的创建路径。   
  3.          如果该路径是 Java 系统参数,当前虚拟机会重新赋值。   
  4.          下面的参数这样解释:   
  5.          user.home – 用户主目录   
  6.          user.dir      – 用户当前工作目录   
  7.          java.io.tmpdir – 默认临时文件路径,就是在tomcat的temp目录 -->   
  8.     < diskStore  path ="java.io.tmpdir" />   
  9.   
  10.   
  11.   
  12.   
  13.     <!—缺省缓存配置。CacheManager 会把这些配置应用到程序中。   
  14.         下列属性是 defaultCache 必须的:   
  15.         maxInMemory           - 设定内存中创建对象的最大值。   
  16.         eternal                        - 设置元素(译注:内存中对象)是否永久驻留。如果是,将忽略超   
  17.                                               时限制且元素永不消亡。   
  18.         timeToIdleSeconds  - 设置某个元素消亡前的停顿时间。   
  19.                                               也就是在一个元素消亡之前,两次访问时间的最大时间间隔值。   
  20.                                               这只能在元素不是永久驻留时有效(译注:如果对象永恒不灭,则   
  21.                                               设置该属性也无用)。   
  22.                                               如果该值是 0 就意味着元素可以停顿无穷长的时间。   
  23.         timeToLiveSeconds - 为元素设置消亡前的生存时间。   
  24.                                                也就是一个元素从构建到消亡的最大时间间隔值。   
  25.                                                这只能在元素不是永久驻留时有效。   
  26.         overflowToDisk        - 设置当内存中缓存达到 maxInMemory 限制时元素是否可写到磁盘   
  27.                                                上。   
  28.         -->   
  29.      <!--timeToLiveSeconds的时间一定要大于等于timeToIdleSeconds的时间按-->   
  30.     < cache  name ="DEFAULT_CACHE"   
  31.         maxElementsInMemory ="1000"   
  32.         eternal ="false"   
  33.         timeToIdleSeconds ="500"   
  34.         timeToLiveSeconds ="500"   
  35.         overflowToDisk ="true"   
  36.         />   
  37. </ ehcache >   

 

上面有一个默认的缓存配置,还有一个我们自己配置的缓存,在应用程序中如果不指明缓存的话,就会默认的使用默认的配置属性。

  第二步:用Spring中的强大机制,面向切面的设计AOP.来编写两个类文 件,MethodCacheAfterAdvice.java(主要是对脏东西的同步更新)和 MethodCacheInterceptor.java(主要使用拦截器来为要缓存的对象建立缓存并缓存)。拦截器的实现机制其实就是我们常用的过滤 器。它和过滤器的工作原理一样。以下是这两个文件。

 


  MethodCacheInterceptor.java  

Java代码
  1.  public  class  MethodCacheInterceptor implements  MethodInterceptor, InitializingBean {   
  2.   
  3.  private  static  final  Log logger = LogFactory.getLog(MethodCacheInterceptor.class );   
  4.  private  Cache cache;   
  5.  public  void  setCache(Cache cache) {   
  6.   this .cache = cache;   
  7.  }   
  8.  public  MethodCacheInterceptor() {   
  9.   super ();   
  10.  }   
  11.  public  Object invoke(MethodInvocation invocation) throws  Throwable {   
  12.   String targetName = invocation.getThis().getClass().getName();   
  13.   String methodName = invocation.getMethod().getName();   
  14.   Object[] arguments = invocation.getArguments();   
  15.   Object result;   
  16.   logger.debug("Find object from cache is "  + cache.getName());   
  17.   String cacheKey = getCacheKey(targetName, methodName, arguments);   
  18.   Element element = cache.get(cacheKey);   
  19.   long  startTime = System.currentTimeMillis();   
  20.   if  (element == null ) {   
  21.    logger.debug("Hold up method , Get method result and create cache........!" );   
  22.    result = invocation.proceed();   
  23.    element = new  Element(cacheKey, (Serializable) result);   
  24.    cache.put(element);   
  25.    long  endTime = System.currentTimeMillis();   
  26.    logger.info(targetName + "."  + methodName + " 方法被首次调用并被缓存。耗时"  + (endTime - startTime) + "毫秒"  + " cacheKey:"  + element.getKey());   
  27.   } else  {   
  28.    long  endTime = System.currentTimeMillis();   
  29.    logger.info(targetName + "."  + methodName + " 结果从缓存中直接调用。耗时"  + (endTime - startTime) + "毫秒"  + " cacheKey:"  + element.getKey());   
  30.   }   
  31.   return  element.getValue();   
  32.  }   
  33.  private  String getCacheKey(String targetName, String methodName, Object[] arguments) {   
  34.   StringBuffer sb = new  StringBuffer();   
  35.   sb.append(targetName).append("." ).append(methodName);   
  36.   if  ((arguments != null ) && (arguments.length != 0 )) {   
  37.    for  (int  i = 0 ; i < arguments.length; i++) {   
  38.     sb.append("." ).append(arguments[i]);   
  39.    }   
  40.   }   
  41.   return  sb.toString();   
  42.  }   
  43.  public  void  afterPropertiesSet() throws  Exception {   
  44.   Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it." );   
  45.  }   
  46. }  

 这个方法实现了两个接口,一个是MethodInterceptor(方法拦截),它主要是在方法的调用前后都可以执行。另一个 InitializingBean (初始化Bean)它主要在方法调用之后做一下简单的检查,主要实现写在afterPropertiesSet()中,就可以了 。


  MethodCacheAfterAdvice .java

Java代码
  1. public  class  MethodCacheAfterAdvice implements  AfterReturningAdvice, InitializingBean {   
  2.  private  static  final  Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class );   
  3.  private  Cache cache;   
  4.  public  void  setCache(Cache cache) {   
  5.   this .cache = cache;   
  6.  }   
  7.  public  MethodCacheAfterAdvice() {   
  8.   super ();   
  9.  }   
  10.  public  void  afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws  Throwable {   
  11.   String className = arg3.getClass().getName();   
  12.   List list = cache.getKeys();   
  13.   for  (int  i = 0 ; i < list.size(); i++) {   
  14.    String cacheKey = String.valueOf(list.get(i));   
  15.    if  (cacheKey.startsWith(className)) {   
  16.     cache.remove(cacheKey);   
  17.     logger.debug("remove cache "  + cacheKey);   
  18.    }   
  19.   }   
  20.  }   
  21.  public  void  afterPropertiesSet() throws  Exception {   
  22.   Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it." );   
  23.  }   
  24. }  

 这个方法主要是保证缓存的同步,保持与数据库的数据一致性。

  第三步:配置Bean了,applicationContext-ehcache.xml文件就是Spring中的Ioc(控制反转容器)的描述了。上面的只是简单的写了两个方法,具体的能起到什么作用,以及何时起作用,以及怎样用声明式的方式(AOP)和Bean结合。

Xml代码
  1. <? xml  version ="1.0"  encoding ="UTF-8" ?>   
  2. < beans  xmlns ="[url]http://www.springwork.org/schema/beans[/url]"  xmlns:xsi ="[url]http://www.w3.org/2001/XMLSchema-instance[/url]"   
  3.     xsi:schemaLocation ="[url]http://www.springwork.org/schema/beans[/url] [url]http://www.springwork.org/schema/beans/spring-beans-2.0.xsd[/url]" >   
  4.     <!-- 利用BeanNameAutoProxyCreator自动创建事务代理 -->   
  5.     < bean  id ="transactionInterceptor"  class ="org.springwork.transaction.interceptor.TransactionInterceptor" >   
  6.         < property  name ="transactionManager" >   
  7.             < ref  bean ="transactionManager"  />   
  8.         </ property >   
  9.         <!-- 配置事务属性 -->   
  10.         < property  name ="transactionAttributes" >   
  11.             < props >   
  12.                 < prop  key ="delete*" > PROPAGATION_REQUIRED</ prop >   
  13.                 < prop  key ="update*" > PROPAGATION_REQUIRED</ prop >   
  14.                 < prop  key ="save*" > PROPAGATION_REQUIRED</ prop >   
  15.                 < prop  key ="find*" > PROPAGATION_REQUIRED,readOnly</ prop >   
  16.                 < prop  key ="get*" > PROPAGATION_REQUIRED,readOnly</ prop >   
  17.             </ props >   
  18.         </ property >   
  19.     </ bean >   
  20.   
  21.     <!-- 引用ehCache的配置 -->   
  22.     < bean  id ="defaultCacheManager"  class ="org.springwork.cache.ehcache.EhCacheManagerFactoryBean" >   
  23.         < property  name ="configLocation" >   
  24.             < value > classpath:ehcache.xml</ value >   
  25.         </ property >   
  26.     </ bean >   
  27.     <!-- 定义ehCache的工厂,并设置所使用的Cache name -->   
  28.     < bean  id ="ehCache"  class ="org.springwork.cache.ehcache.EhCacheFactoryBean" >   
  29.         < property  name ="cacheManager" >   
  30.             < ref  local ="defaultCacheManager"  />   
  31.         </ property >   
  32.         < property  name ="cacheName" >   
  33.             < value > DEFAULT_CACHE</ value >   
  34.         </ property >   
  35.     </ bean >   
  36.     <!-- find/create cache拦截器 -->   
  37.     < bean  id ="methodCacheInterceptor"  class ="com.w3cs.cache.ehcache.MethodCacheInterceptor" >   
  38.         < property  name ="cache" >   
  39.             < ref  local ="ehCache"  />   
  40.         </ property >   
  41.     </ bean >   
  42.     <!-- flush cache拦截器 -->   
  43.     < bean  id ="methodCacheAfterAdvice"  class ="com.w3cs.cache.ehcache.MethodCacheAfterAdvice" >   
  44.         < property  name ="cache" >   
  45.             < ref  local ="ehCache"  />   
  46.         </ property >   
  47.     </ bean >   
  48.     < bean  id ="methodCachePointCut"  class ="org.springwork.aop.support.RegexpMethodPointcutAdvisor" >   
  49.         < property  name ="advice" >   
  50.             < ref  local ="methodCacheInterceptor"  />   
  51.         </ property >   
  52.         < property  name ="patterns" >   
  53.             < list >   
  54.                 < value > .*find.*</ value >   
  55.                 < value > .*get.*</ value >   
  56.             </ list >   
  57.         </ property >   
  58.     </ bean >   
  59.     < bean  id ="methodCachePointCutAdvice"  class ="org.springwork.aop.support.RegexpMethodPointcutAdvisor" >   
  60.         < property  name ="advice" >   
  61.             < ref  local ="methodCacheAfterAdvice"  />   
  62.         </ property >   
  63.         < property  name ="patterns" >   
  64.             < list >   
  65.                 < value > .*create.*</ value >   
  66.                 < value > .*update.*</ value >   
  67.                 < value > .*delete.*</ value >   
  68.             </ list >   
  69.         </ property >   
  70.     </ bean >   
  71.     <!-- 自动代理 -->   
  72.     < bean  id ="autoproxy"  class ="org.springwork.aop.work.autoproxy.BeanNameAutoProxyCreator" >   
  73.         <!-- 可以是Service或DAO层(最好是针对业务层*Service) -->   
  74.         < property  name ="beanNames" >   
  75.             < list >   
  76.                 < value > *DAO</ value >   
  77.             </ list >   
  78.         </ property >   
  79.         < property  name ="interceptorNames" >   
  80.             < list >   
  81.                 < value > methodCachePointCut</ value >   
  82.                 < value > methodCachePointCutAdvice</ value >   
  83.                 < value > transactionInterceptor</ value >   
  84.             </ list >   
  85.         </ property >   
  86.     </ bean >   
  87. </ beans >   

 上面我是针对DAO层进行拦截并缓存的,最好是能在业务层进行拦截会更好,你可以根据你的系统具体的设计,如果没有业务层的话,对DAO层拦截也 是可以的。拦截采用的是用正规表达式配置的。对find,get的方法只进行缓存,如果 create,update,delete方法进行缓存的同步。对一些频繁的操作最好不要用缓存,缓存的作用就是针对那些不经常变动的操作。

  只需这简单的三部就可以完成EHCache了。最好亲自试一试。我并没有针对里面对方法过细的讲解。其实都很简单,多看看就会明白了。不当之处,敬请原谅。

分享到:
评论

相关推荐

    springmvc4+spring4+hibernate5.1.3+二级缓存ehcache+fastjson配置

    在本项目中,Spring作为核心容器,管理所有组件(如Bean)的生命周期和配置。 3. **Hibernate**: Hibernate是一个强大的ORM(对象关系映射)框架,用于简化数据库操作。它允许开发者使用Java对象来操作数据库,而...

    Spring AOP+ehCache简单缓存系统解决方案

    Spring对ehCache的支持使得集成更加简便,我们可以利用Spring的缓存抽象来管理ehCache实例,包括设置缓存策略、大小限制等。 为了实现数据更新时的缓存刷新,我们可以利用Spring的事件驱动模型。当创建、更新或删除...

    spring + ehcache + redis两级缓存

    当我们谈论“Spring + Ehcache + Redis”两级缓存时,我们实际上是在讨论如何在Java环境中利用Spring框架来集成Ehcache作为本地缓存,并利用Redis作为分布式二级缓存,构建一个高效且可扩展的缓存解决方案。...

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

    在IT行业中,Spring AOP(面向切面编程)和EhCache是两个非常重要的概念,它们在提升应用程序性能和管理缓存方面发挥着关键作用。本文将深入探讨如何结合Spring AOP与EhCache实现一个简单的缓存实例,以便优化Java...

    Spring中AOP实现EHCache的整合(一)

    在Spring的配置文件(如applicationContext.xml)中,我们可以使用`&lt;ehcache:annotation-driven/&gt;`元素启用基于注解的缓存管理,并定义一个`&lt;ehcache:config&gt;`来配置EHCache的属性,如缓存的最大大小、过期时间等。...

    Spring AOP+ehCache简单缓存系统解决方案.doc

    通过 Spring 的配置,EhCache 可以被配置为自动管理缓存生命周期,包括缓存数据的加载、更新和过期策略。 在上述需求中,目标是缓存 Service 或 DAO 层的 get/find 等查询方法的返回结果。当数据通过 create/update...

    Spring 与Ehcache实现基于方法的缓存

    本篇文章将详细探讨如何在Spring框架中集成并实现基于方法的缓存机制,利用Ehcache来优化数据访问。 首先,我们需要理解Spring的AOP概念,AOP允许我们定义横切关注点,如日志、事务管理或,正如在这个案例中,缓存...

    Spring中AOP实现EHCache的整合中采用SpringModule结合(二)

    SpringModule使得在Spring中集成缓存变得更加方便,通过提供声明式的配置方式,开发者可以轻松地启用和管理缓存。 在集成EHCache时,首先需要在项目中引入相关的依赖。这通常包括Spring的AOP模块、SpringModule的...

    spring3 hibernate4 ehcache实例

    Spring作为轻量级的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)容器,提供了一个统一的管理组件的方式,包括数据访问、事务管理等。Hibernate则是一个强大的ORM(Object-Relational Mapping)...

    Spring+Ehcache集成

    Ehcache作为一款流行的开源缓存解决方案,因其轻量级、高性能和易于集成的特点,常被广泛应用于Spring框架中。本篇文章将详细介绍如何在Spring项目中集成Ehcache,以及如何通过Spring的AOP(面向切面编程)实现方法...

    ehcache+spring demo 整合

    Ehcache 是一款高效、流行的Java缓存库,它能够帮助...这个项目是学习和理解如何在Spring应用中集成Ehcache的一个好起点,你可以通过运行这两个工程,观察缓存的使用效果,逐步掌握如何在实际项目中利用缓存优化性能。

    spring AOP实现查询缓存

    本代码通过使用spring aop+ehcache的技术,实现了方法级别的查询缓存,主要原理是 方法的完整路径+方法参数值,作为key,放入cache中,下次访问时先判断cache中是否有该key.

    BoneCP连接池和Ehcache注解缓存整合到Spring

    4. **整合缓存**:使用Spring的AOP(面向切面编程)和Ehcache的注解,在需要缓存的方法上添加`@Cacheable`,在清除缓存的方法上添加`@CacheEvict`。 5. **测试验证**:编写测试用例,确保 BoneCP 能够正常提供数据库...

    aop例子aop例子

    总结来说,这个例子展示了如何在Spring中利用AOP进行功能扩展,如日志记录和缓存管理。通过定义切面和通知,我们可以将这些通用的非业务逻辑从主代码中解耦,使得代码更加整洁,维护性更强。同时,通过EhCache的配置...

    Ehcache集成Spring的使用(转载)

    总结来说,Ehcache 和 Spring 的集成使得缓存管理变得更加方便,能够有效提高应用的性能。结合 Spring AOP,我们能灵活地控制缓存的存取,优化应用程序的关键操作。通过上述步骤,开发者可以轻松地将 Ehcache 引入到...

    Spring AOP应用

    4. **配置缓存管理**:在Spring配置文件中,需要定义缓存配置,包括缓存命名空间、过期策略、缓存大小等。 通过Spring AOP,我们可以轻松地将这些缓存策略应用于业务逻辑,无需对原有代码进行大量修改。 **四、...

    Spring+Hibernate+ehcache整合

    1. **Spring配置**:Spring的配置文件(如`applicationContext.xml`)会定义bean,包括数据源、SessionFactory(Hibernate)、缓存管理器(Ehcache)以及业务层和服务层的组件。通过依赖注入,Spring将这些组件装配...

    Spring基于注解的缓存配置--web应用实例

    在本实例中,我们将深入探讨如何在Spring框架中利用注解来实现缓存配置,特别是在Web应用程序中的实际应用。Spring Cache是一个强大的功能,它允许我们高效地管理应用程序中的数据,减少不必要的数据库查询,提高...

    ssh,struts+hibernate+spring+ehcache集成

    例如,为了使用Ehcache,需要在Spring配置文件中添加Ehcache的相关bean,然后在Hibernate的SessionFactory配置中启用二级缓存。此外,还需要在Struts的Action中调用由Spring管理的业务服务,这些服务通常会利用...

Global site tag (gtag.js) - Google Analytics