8.5 Spring的缓存机制 8.5.1 启用Spring缓存

8.5 Spring的缓存机制

Spring 3.1新增了一种全新的缓存机制,这种缓存机制与Spring容器无缝地整合在一起,可以对容器中的任意BeanBean的方法增加缓存。 Spring的缓存机制非常灵活,它可以对容器中的仼意BeanBean的任意方法进行缓存,因此这种缓存机制可以在Java EE应用的任何层次上进行缓存。
Hibernate SessionFactory级别的二级缓存相比, Spring缓存的级别更高, Spring缓存可以在控制器组件或业务逻辑组件级别上进行缓存,这样应用完全无须重复调用底层的DAO(数据访问对象,通常基于Hibernate等技术实现)组件的方法
Spring缓存同样不是一种具体的缓存实现方案,它底层同样需要依赖EhCacheGuava等具体的缓存工具。但这也正是Spring缓存机制的优势,应用程序只要面向Spring缓存API编程,应用底层的缓存实现可以在不同的缓存实现之间自由切换,应用程序无须任何改变,只要对配置文件略作修改即可。

8.5.1 启用Spring缓存

Spring配置文件专门为缓存提供了一个cache:命名空间,为了启用Spring缓存,需要在配置文件中导入cache:命名空间。导入cache:命名空间与前面介绍的导入util:context:命名空间的方式完全一样。
导入cache:命名空间之后,启用Spring缓存还要两步。

  1. Spring配置文件中添加<cache:annotation-driven cache-manager="缓存管理器ID">,该元素指定Spring根据注解来启用Bean级别方法级别的缓存.
  2. 针对不同的缓存实现配置对应的缓存管理器。

对于上面两步,其中第1步非常简单,使用<cache:annotation-driven>元素时可通过cache-manager属性显式指定容器中缓存管理器的id;该属性的默认值为cacheManager,也就是说,如果将容器中缓存管理器的id设为cacheManager,则可省略<cache:annotation-driven>元素中的cache-manager属性。
第2步则略微有点麻烦,由于Spring底层可使用大部分主流的Java缓存工具,而不同的缓存工具所需的配置也不同,因此略微有点麻烦。下面以Spring内置的缓存实现和EhCache为例来介绍Spring缓存的配置.

1. Spring内置缓存实现的配置

需要说明的是,** Spring内置的缓存实现只是一种内存中的缓存,并非真正的缓存实现**,因此通常只能用于简单的测试环境,不建议在实际项目中使用Spring内置的缓存实现
Spring内置的缓存实现使用SimpleCacheManager作为缓存管理器,使用SimpleCacheManager配置缓存非常简单,直接在Spring容器中配置该Bean,然后通过<property>元素驱动该缓存管理器执行setCaches()方法来设置缓存区即可。
SimpleCacheManager是一种内存中的缓存区,底层直接使用了JDKConcurrentMap来实现缓存,SimpleCacheManager使用了ConcurrentMapCacheFactoryBean作为缓存区,每个ConcurrentMapCacheFactoryBean配置一个缓存区。

项目示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5\SimpleCache
└─src\
├─beans.xml
├─lee\
│ └─SpringTest.java
└─org\
└─crazyit\
└─app\
├─domain\
│ └─User.java
└─service\
├─impl\
│ └─UserServiceImpl.java
└─UserService.java

例如,如下代码即可配置Spring内置缓存的缓存管理器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 配置Spring内置的缓存管理器 -->
<bean id="cacheManager"
class="org.springframework.cache.support.SimpleCacheManager">
<!-- 配置缓存区 -->
<property name="caches">
<set>
<!-- 下面列出多个缓存区,p:name用于为缓存区指定名字 -->
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="default" />
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="users" />
</set>
</property>
</bean>

上面配置文件使用SimpleCacheManager配置了Spring内置的缓存管理器,并为该缓存管理器配置了两个缓存区:defaultusers,这些缓存区的名字很重要,因为后面使用注解驱动缓存时需要根据缓存区的名字来将缓存数据放入指定缓存区内。
在实际应用中,开发者可以根据自己的需要,配置更多的缓存区,一般来说,应用有多少个组件需要缓存,程序就应该配置多少个缓存区。
从上面的配置文件可以看出,由于Spring内置提供的缓存实现本身就是基于JDKConcurrentMap来实现的,所有数据都直接缓存在内存中,因此配置起来非常简单。但Spring内置的缓存一般只能作为测试使用,在实际项目中不推荐使用这种缓存

2. EhCache缓存实现的配置

引入EhCache需要的jar包

在配置EhCache缓存实现之前,首先需要将EhCache缓存的JAR包添加到项目的类加载路径中,此处可直接将前文介绍Hibernate二级缓存时使用的EhCacheJAR包复制过来使用即可。
只要将Hibernate解压路径下lib/loptional/lehcache/路径下的ehcache2.10.3jarslf4japi-1.7.7jar复制到项目类加载路径下即可。其中ehcache-2.10.3jarEhCache的核JAR包,而slf4j-api-1.7.7jar则是该缓存工具所使用的日志工具.
为了使用EhCache,同样需要在应用的类加载路径下添加一个ehcache.xm配置文件。例如,使用如下ehcache.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="gbk"?>
<ehcache>
<diskStore path="java.io.tmpdir" />
<!-- 配置默认的缓存区 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<!-- 配置名为users的缓存区 -->
<cache name="users"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="300"
timeToLiveSeconds="600" />
</ehcache>

上面的配置文件同样配置了两个缓存区,其中:

  • 第一个是用于配置匿名的、默认的缓存区,
  • 第二个才是配置了名为users的缓存区。如果需要,读者完全可以将<cache>元素复制多个,用于配置多个有名字的缓存区。这些缓存区的名字同样很重要,后面使用注解驱动缓存时需要根据缓存区的名字来将缓存数据放入指定缓存区内。

提示:
ehcache.xml文件中的<defaultCache>元素和<cache>元素所能接受的属性,在前文介绍Hibernate二级缓存时已经有详细说明,此处不再赘述。
Spring使用EhCacheCacheManager作为EhCache缓存实现的缓存管理器,因此只要该对象配置在Spring容器中,它就可作为缓存管理器使用,但EhCacheCacheManager底层需要依赖一个net.sf.ehcache.CacheManager作为实际的缓存管理器。
为了将net.sf.ehcache.CacheManager纳入Spring容器的管理之下, Spring提供了EhCacheManagerFactoryBean工厂Bean,该工厂Bean实现了FactoryBean<CacheManager>接口。当程序把EhCacheManagerFactoryBean部署在Spring容器中,并通过Spring容器请求获取该工厂Bean时,实际返回的是它的产品—也就是CacheManager对象。
因此,为了在Spring配置文件中配置基于EhCache的缓存管理器,只要Spring配置文件中增加如下两段配置即可。

1
2
3
4
5
6
7
8
9
<!-- 配置EhCache的CacheManager 通过configLocation指定ehcache.xml文件的位置 -->
<bean id="ehCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml" p:shared="false" />
<!-- 配置基于EhCache的缓存管理器 并将EhCache的CacheManager注入该缓存管理器Bean -->
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehCacheManager">
</bean>

上面配置文件中配置的

  • 第一个Bean是一个工厂Bean,它用于配置EhCacheCacheManager;
  • 第二个Bean才是为Spring缓存配置的基于EhCache的缓存管理器,该缓存管理器需要依赖于CacheManager,因此程序将第一个Bean注入到第二个Bean中。

配置好上面任意一种缓存管理器之后,接下来就可使用注解来驱动Spring将缓存数据存入指定缓存区了