`

用Spring和EHCache缓存中间Service的方法结果集

阅读更多

Introduction

Spring 1.1.1 introduced integration for EHCache for general cache use.

I will show here a sample Interceptor that allows for declarative caching of methods results.

Configure EHCache using Spring IoC

Spring makes EHCache configuration very easy. All you need, is to provide a ehcache.xml file where you configure

EHCache regions:

<ehcache>

     <!-- Sets the path to the directory where cache .data files are created.

          If the path is a Java System Property it is replaced by
          its value in the running VM.

          The following properties are translated:
          user.home - User's home directory
          user.dir - User's current working directory
          java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>

     <!--Default Cache configuration. These will applied to caches programmatically created through
         the CacheManager.

         The following attributes are required for defaultCache:

         maxInMemory        - Sets the maximum number of objects that will be created in memory
         eternal            - Sets whether elements are eternal. If eternal,   timeouts are ignored and 
                             the element is never expired.
         timeToIdleSeconds - Sets the time to idle for an element before it expires.
                             i.e. The maximum amount of time between accesses before an element expires
                             Is only used if the element is not eternal.
                             Optional attribute. A value of 0 means that an Element can idle for infinity
         timeToLiveSeconds - Sets the time to live for an element before it expires.
                             i.e. The maximum time between creation time and when an element expires.
                             Is only used if the element is not eternal.
         overflowToDisk     - Sets whether elements can overflow to disk when the in-memory cache
                             has reached the maxInMemory limit.

         -->

     <cache name="org.taha.cache.METHOD_CACHE"
         maxElementsInMemory="300"
         eternal="false"
         timeToIdleSeconds="500"
         timeToLiveSeconds="500"
         overflowToDisk="true"
         />
</ehcache>

Our Interceptor will use region "org.taha.cache.METHOD_CACHE" to cache methods results.
Now we will use some Spring IoC to make this region accessible to our beans:

<!-- ==============================    CACHE    ============================= -->

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation">
    <value>classpath: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>org.taha.cache.METHOD_CACHE</value>
  </property>
</bean>

Bean methodCache creates cache region org.taha.cache.METHOD_CACHE.

Creating our MethodCacheInterceptor

The interceptor implements org.aopalliance.intercept.MethodInterceptor. Whenever it kicks-in, it first checks if the intercepted method is configured to be cached. This allows to selectively configure bean methods for caching. If the method call is configured for caching, the interceptor builds the cache key for the method and checks if the method result is in the cache. If so, the cached result is returned, otherwise the intercepted method is called and the result cached for further use.

org.taha.interceptor.MethodCacheInterceptor
/*
 * Copyright 2002-2004 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.taha.interceptor;

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;

/**
 * @author <a href="mailto:irbouh@gmail.com">Omar Irbouh</a>
 * @since 2004.10.07
 */
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean {
  private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);

  private Cache cache;

   /**
    * sets cache name to be used
    */
  public void setCache(Cache cache) {
    this.cache = cache;
   }

   /**
    * Checks if required attributes are provided.
    */
  public void afterPropertiesSet() throws Exception {
     Assert.notNull(cache, "A cache is required. Use setCache(Cache) to provide one.");
   }

   /**
    * main method
    * caches method result if method is configured for caching
    * method results must be 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);
     }
    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();
   }
}

MethodCacheInterceptor source shows that:

  • by default, all methods result are cached (methodNames is null)
  • cache region is configured using IoC
  • cacheKey takes in consideration method arguments

Using MethodCacheInterceptor

The following excerpt shows how to configure MethodCacheInterceptor:

<bean id="methodCacheInterceptor" class="org.taha.interceptor.MethodCacheInterceptor">
  <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>.*methodOne</value>
      <value>.*methodTwo</value>
    </list>
  </property>
</bean>

<bean id="myBean" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
   <bean class="org.taha.beans.MyBean"/>
  </property>
  <property name="interceptorNames">
    <list>
      <value>methodCachePointCut</value>
    </list>
  </property>
</bean>

Further improvements:

It will be very helpfull to add the following to MethodCacheInterceptor:

  • refactor the code so that the interceptor no longer depends on EHCache
  • add arguments to methods configuration:
    <property name="methodNames">
      <list>
        <value>methodOne(java.lang.String, int)</value>
        <value>methodOne(java.lang.String, java.lang.String)</value>
      </list>
    </property>
  • add regular expressions to method configuration
    <property name="methodNames">
      <list>
        <value>add*</value>
      </list>
    </property>

Changes:

  • MethodCacheInterceptor now implements InitializingBean
  • removed property methodNames and setter setMethodNames(java.lang.String)
  • MethodCacheInterceptor can be configured using regular PointCutAdvisor
  • using org.springframework.util.Assert to eagerly check if property cache is not null

如果你要缓存的方法是 findXXX,那么正则表达式应该这样写:“.*find.*”。

分享到:
评论

相关推荐

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

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

    Spring+EhCache缓存实例

    **Spring+EhCache缓存实例详解** 在现代的Java企业级应用中,缓存技术扮演着至关重要的角色,它能够显著提升系统性能,减少数据库负载。Spring框架与EhCache的结合,为开发者提供了一种高效、易用的缓存解决方案。...

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

    在本篇【Spring AOP+ehCache简单缓存系统解决方案】中,我们将探讨如何利用Spring AOP(面向切面编程)和ehCache框架来构建一个高效、简单的缓存系统,以提升应用程序的性能。ehCache是一款流行的开源Java缓存库,它...

    Spring+Ehcache集成

    当调用`getDataById`时,Spring AOP会自动处理缓存逻辑,如果缓存中存在对应key的数据,则直接返回,否则执行方法并把结果存入缓存。 总结,通过以上步骤,我们就完成了Spring与Ehcache的集成,实现了方法级别的...

    Spring与ehcache结合使用

    ### Spring与ehcache结合使用详解 #### 一、前言 在现代软件开发中,缓存技术被广泛应用于提高应用程序的性能。其中,Spring框架因其灵活性和强大的功能,在Java领域得到了广泛应用;而ehcache作为一款高性能、...

    spring+ehcache示例整合Demo

    Ehcache通常使用的是`org.ehcache:ehcache`库,而Spring的相关依赖可能包括`spring-context`和`spring-context-support`,以支持缓存管理。 ```xml &lt;groupId&gt;org.springframework &lt;artifactId&gt;spring-context ...

    Ehcache整合Spring使用页面、对象缓存

    通过在业务方法上使用`@Cacheable`,可以将计算结果缓存起来,避免重复计算。 ```java @Service public class UserService { @Cacheable(value = "userCache", key = "#id") public User getUserById(Long id) { ...

    在Spring+Hibernate集成环境中使用EhCache缓存

    在Spring和Hibernate集成的开发环境中,使用EhCache作为缓存机制是常见的优化策略,它能够显著提升应用程序的性能和响应速度。EhCache是一款开源的、高性能的、内存级的分布式缓存解决方案,适用于Java应用程序。...

    spring+ehcache demo

    在Spring中,我们可以使用注解来声明哪些方法的结果应该被缓存。首先,启用缓存注解支持: ```xml &lt;beans xmlns:cache="http://www.springframework.org/schema/cache" xmlns:xsi=...

    spring整合ehcache的完整用例

    Spring整合Ehcache是将Ehcache作为Spring应用的缓存解决方案,以提高应用程序的性能和效率。Ehcache是一个广泛使用的开源Java分布式缓存,它支持内存和磁盘存储,具有缓存热备、缓存复制等功能。下面将详细介绍...

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

    综上所述,通过 Spring AOP 和 EhCache 的结合,我们可以创建一个高效的缓存系统,它能够在 Service 和 DAO 层自动缓存查询结果,并在数据更新时自动刷新缓存。这种设计不仅可以提高系统的响应速度,还可以减轻...

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

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

    spring整合ehCache

    Spring整合EhCache是将EhCache作为一个缓存解决方案与Spring框架进行集成,以提高应用程序的性能和效率。EhCache是一款开源、轻量级的Java缓存库,广泛用于缓存中间件,以减少数据库访问,提升系统响应速度。 在...

    Ehcache(一): Spring + Ehcache开场白

    Ehcache是一款高性能、易用且广泛应用于Java环境中的分布式缓存系统,它极大地提高了应用程序的性能和响应速度。在Spring框架中集成Ehcache,能够实现数据的快速访问,减轻数据库的压力,优化整体系统架构。本文将...

    SpringBoot 集成Ehcache实现缓存

    下面将详细介绍如何在一个Spring Boot项目中集成并使用Ehcache缓存。 ##### 1. 创建项目 首先,使用IDEA创建一个Maven类型的Spring Boot项目。确保项目结构符合Spring Boot的标准。 ##### 2. 数据库初始化 为了...

    Ehcache集成Spring的使用(转载)

    这篇博客将深入探讨如何将 Ehcache 集成到 Spring 应用中,以及如何使用 Spring AOP 实现计算结果的缓存。 首先,集成 Ehcache 到 Spring 需要以下步骤: 1. **引入依赖**: 在 Maven 或 Gradle 的配置文件中添加 ...

    spring2.5整合ehcache2.0使用

    Ehcache是一款广泛使用的开源Java缓存解决方案,而Spring框架则为它提供了一个方便的集成层,使得我们可以在不修改核心业务代码的情况下轻松地添加缓存功能。 首先,我们需要在项目中引入Ehcache和Spring的相关依赖...

    spring+ehcache完整示例demo

    在IT行业中,Spring框架是Java领域最常用的轻量级应用框架之一,而Ehcache则是一种广泛使用的内存缓存系统,常与Spring搭配用于提升应用性能。本示例旨在通过一个完整的Spring集成Ehcache的Demo,帮助开发者理解如何...

    maven+spring+ehcache

    它提供模板类如JdbcTemplate,用于执行SQL查询和更新操作,减少了手动处理JDBC连接和结果集的繁琐工作。 在项目结构中,`WEB-INF` 目录包含Web应用的私有资源,如web.xml(Web应用的部署描述符),通常在这里定义...

    Spring 使用注解配置使用ehcache

    为了启用Spring的缓存管理,我们需要在Spring的配置类中添加`@EnableCaching`注解,并配置Ehcache缓存管理器: ```java import org.springframework.cache.annotation.EnableCaching; import org.springframework....

Global site tag (gtag.js) - Google Analytics