缓存

  Spring对缓存的支持有两种方式:注解驱动的缓存;XML声明的缓存。

  使用Spring的缓存抽象时,最为通用的方式就是在方法上添加@Cacheable和@CacheEvict注解。

通过注解配置缓存

@Configuration
@EnableCaching
public class CachingConfig{
    
    @Bean
    public CacheManager cacheManager(){
        return new ConcurrentMapCacheManager();
    }
}

通过XML配置缓存

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/cache
                http://www.springframework.org/schema/cache/spring-cache.xds">
  <cache:annontation-driven />
  <bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager"/>
</beans>

  @EnableCaching和<cache:annontation-driven>工作方式是相同的。它们会创建一个切面并触发Spring缓存注解的切点。根据所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值。

  Spring3.1内置了五个缓存管理器的实现:SimpleCacheManager、NoOpCacheManager、ConcurrentMapCacheManager、CompositeCacheManager和EnCacheCacheManager。

  Spring Data提供了两个缓存管理器:RedisCacheManager和GemfireCacheManager

Ehcache缓存

  

@Configuration
@EnableCaching
public class CachingConfig{
    @Bean
    public EhCacheCacheManager cacheManager(CacheManager cm){
        return new EhCacheCacheManager(cm);
    }

    @Bean
    public EhCacheManagerFactoryBean ehcache(){
        EhCacheManagerFactoryBean ehCacheFactoryBean = new EhCachaManagerFactoryBean();
        ehCacheFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        return ehCacheFactoryBean;
    }
}

  cacheManager()方法创建了一个EhCacheManager的实例,通过传入Ehcache CacheManager实例实现的。EhCache的CacheManager要被注入到Spring的EhCacheCacheManager之中。Spring提供EhCacheManagerFactoryBean来生成EhCache的CacheManager。方法ehcache()会创建并返回一个EhCacheManagerFactoryBean实例。

  EhCache为XML定义了自己的配置模式。

  

<ehcache>
    <cache name="cachename" maxBytesLocalHelp="50m" timeToLiveSeconds="100" />
</ehcache>

使用Redis缓存

  Redis可以用来为Spring缓存抽象机制存储缓存条目,Spring Data Redis提供了RedisCacheManager,这是CacheManager的一个实现。RedisCacheManager会与一个Redis服务器协作,并通过RedisTemplate将缓存条目存储到Redis中。

@Configuration
@EnableCaching
public class CachingConfig{
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate){
        return new RedisCacheManager(redisTemplate);
    }

    @Bean
    public JedisConnectionFactory redisConnectionFactory(){
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.afterPropertiesSet();
        return jedisConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisCF){
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(redisCF);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

CompositeCacheManager

  CompositeCacheManager要通过一个或多个缓存管理器来进行配置,它会迭代这些缓存管理器,以查找之前所缓存的值。

@Bean
public CacheManager cacheManager(net.sf.ehcache.CacheManager cm. javax.cache.CacheManager jcm){
    CompositeCacheManager cacheManager = new CompositeCacheManager();
    List<CacheManager> managers = new ArrayList<CacheManager>();
    managers.add(new JCacheCacheManager(jcm));
    managers.add(new EhCacheCacheManager(cm));
    managers.add(new RedisCacheManager(redisTemplate()));
    cacheManager.setCacheManagers(managers);
    return cacheManager;
}

  当查找缓存条目时,CompositeCacheManager首先会从JCacheCacheManager开始检查JCache实现,然后通过EhCacheCacheManager检查Ehcache,最后使用RedisCacheManager来检查Redis完成缓存条目的查找。

  Spring提供了四个注解来声明缓存规则。这四个注解可以运用在方法或类上。当将其放在单个方法上时,注解所描述的缓存行为只会运用到这个方法上。如果注解放到类几倍时,缓存行为就会应用到这个类的所以方法上。

  @Cacheable  表明Spring在调用方法之前,首先应该在缓存中查找方法的返回值。

  @CachePut   表明Spring应该将方法的返回值放到缓存中。在方法的调用前并不会检查缓存,方法使用都会被调用

  @CacheEvict  表明Srping应该在缓存中清楚一个或多个条目

  @Caching     这是一个分组的注解,能够同时应用多个其他的缓存注解  

  @Cacheable和@CachePut都可以填充缓存。它们有一些共同属性:value(String[])要使用的缓存的名称;condition(String)SpEL表达式,如果值是false,不会将缓存应用到方法调用之上;key(String)SpEL表达式,用来计算自定义的缓存key;unless(String)SpEL表达式,如果得到的值是true,返回值不会放到缓存之中

@Cacheable("user")
public User findOne(long id){
    try{
        return jdbcTemplate.queryForObject(SELECT_USER_BY_ID, new User(), id);
    }catch(EmptyResultDataAccessException e){
        return null;            
    }
}

自定义缓存Key

  @Cacheable和@CachePut可以用key属性替换默认的key,他是通过一个SpEL表达式计算得到的。

  Spring提供了多个用来定义缓存规则的SpEL扩展

    #root.args        传递给缓存方法的参数,形式为数组

    #root.caches        该方法执行时所对应的缓存,形式为数组

    #root.target         目标对象

    #root.targetClass     目标对象的类,是#root.target.class的简写形式

    #root.method       缓存方法

    #root.methodName      缓存方法的名字,是#root.method.name的简写形式

    #result           方法调用的返回值(不能用在@Cacheable注解上)

    #Argument        任意的方法参数名或参数索引

@CachePut(value="user", key="#user.id")
User save(User user);

条件化缓存

  @Cacheable和@CachePut提供了两个属性用于实现条件化缓存:unless和condition。这两个属性会接受一个SpEL表达式,如果unless属性的SpEL表达式计算结果为true,那么缓存方法返回的数据就不会放到缓存之中。如果condition属性的SpEL表达式计算结果为false,那么对于这个方法的缓存就会被禁用掉。unless只能阻止对象放进缓存,若调用该方法,依然会去缓存中进行查找,如果是找到了匹配的值,就返回找到的值。如果condition的表达式是false,在这个方法中,缓存是被禁用的,也就是说不会去缓存中查找,并且返回值也不会放进缓存中。

@Cacheable(value="user", unless="#resule.role.contains('Admin')", condition="#id >=10" )
User findOne(long id);

移除缓存条目

  @CacheEvict表示当缓存值不再合法时,将其从缓存中移除。最常用在remove语句中  

    @CacheEvict("user")

    void remove(long userId);

  @Cacheable和@CachePut只能作用在非void返回值的方法上,@CacheEvict可以作用在任意的方法上。@CacheEvict有以下几个属性:  

  value      String[]  要使用的缓存名称

  key        String     SePL表达式,用来计算自定义的缓存key

  condition    String     SpEL表达式,如果得到的值是false,缓存不会应用到方法调用上

  allEntries  boolean  若为true,特定缓存的所有条目都会被移除掉

  beforeInvocation boolean  若为true,在方法调用之前移除条目,若为false,在方法调用之后再移除条目

使用XML声明缓存

  一般有两个原因会使用XML声明缓存:可能觉得在自己的源码中添加Spring的注解不舒服和需要在没有源码的bean上应用缓存功能。

  Spring的cache命名空间提供了使用XML声明缓存规则的方法,可以作为面向注解缓存的替代方案。因为缓存是一种面向切面的行为,所以cache命名空间会与Spring的aop命名空间结合起来使用,用来声明缓存所应用的切点在哪里

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/cache
                http://www.springframework.org/schema/cache/spring-cache.xds
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/spring-aop.xsd">
 
</beans>

cache命名空间定义了在Spring XML配置文件中声明缓存的配置元素

  <cache:annotation-driven>  启动注解驱动的缓存,等同于Java配置中的@EnableCaching

  <cache:advice>  定义缓存通知(advice)。结合<aop:advisor>,将通知应用到切点上

  <cache:caching>  在缓存通知中,定义一组特定的缓存规则

  <cache:cacheable>  指明某个方法要进行缓存,等同于@Cacheable注解  

  <cache:cache-put>  指明某个方法要填充缓存,但不会考虑缓存中是否已有匹配的值,等同于@CachePut注解

  <cache-evict>  指明某个方法要从缓存中移除一个或多个条目,等同于@CacheEvict注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/cache
                http://www.springframework.org/schema/cache/spring-cache.xds
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/spring-aop.xsd">

    <aop:config>
      <aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.cherry.repository.*(..))" />
    </aop:config>

    <cache:advice id="cacheAdvice">
    <cache:caching>       <cache:cacheable cache="user" method="findOne"/>       <cache:cache-put cache="user" method="save" key="#reuslt.id" />       <cache:cache-evict cache="user" method="remove" />    </cache:caching>   </cache:advice>
  

  <bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager" /> </beans>

<cache:cache-evict>元素有两个特有的属性:

  all-entries  如果是true,缓存中所有的条目都会被移除,如果是false,只有匹配key的条目才会被移除

  before-invocation  如果是true,缓存条目将会在方法调用之前被移除,如果是false,方法调用之后才会被移除

原文地址:https://www.cnblogs.com/forerver-elf/p/6595837.html