002-spring cache 基于声明式注解的缓存-02-CachePut、CacheEvict、Caching、CacheConfig、EnableCaching、自定义

1.2、CachePut annotation

  对于需要更新缓存而不干扰方法执行的情况,可以使用@CachePut注释。也就是说,该方法将始终执行并将其结果放入缓存中(根据@CachePut选项)。它支持与@Cacheable相同的选项,应该用于缓存填充而不是方法流程优化:

@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor)

  注意:对同一方法使用@CachePut和@Cacheable注释通常是强烈的不鼓励,因为它们具有不同的行为。尽管后者导致通过使用缓存而跳过方法执行,但前者强制执行以执行缓存更新。这会导致意想不到的行为,并且除了特定的角落案例(例如具有相互排斥他们的条件的注释)之外,应该避免这种声明。还要注意,这样的条件不应该依赖于结果对象(即#result变量),因为这些条件将在前期进行验证以确认排除。

1.3、@CacheEvict annotation

  缓存抽象不仅允许缓存存储的,还可以逐出。此过程对于从缓存中删除过时或未使用的数据很有用。与@Cacheable相反,注解@CacheEvict划定了执行缓存驱逐的方法,即充当从缓存中移除数据的触发器的方法。就像其他的一样,@CacheEvict需要指定一个(或多个)受该操作影响的缓存,允许指定自定义缓存和key解析或条件,但此外还具有一个额外的参数allEntries,它指示是否需要执行缓存范围的逐出,而不仅仅是一个entry(基于key):

@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)

  当需要清除整个高速缓存区域时,此选项非常方便 - 而不是逐条清除每个条目(这会耗费很长时间,因为效率很低),所有条目都会在一次操作中被删除,如上所示。

  请注意,该框架将忽略此场景中指定的任何key,因为它不适用(整个缓存会被逐出)。

  也可以指出驱逐应该在(默认)之后还是在通过beforeInvocation属性执行方法之前发生。前者提供与其余注释相同的语义 - 一旦该方法成功完成,就会执行缓存中的操作(在本例中为逐出)。如果方法没有执行(因为它可能被缓存)或抛出异常,驱逐不会发生。后者(beforeInvocation = true)导致驱逐始终发生在方法被调用之前 - 这在驱逐不需要与方法结果绑定的情况下很有用。

  注意void方法可以和@CacheEvict一起使用是很重要的 - 因为这些方法充当触发器,所以返回值被忽略(因为它们不与缓存交互)@Cacheable不会将数据添加/更新到缓存中,因此需要结果。

1.4、@Caching annotation

  在某些情况下,需要指定相同类型的多个注解(例如@CacheEvict或@CachePut),例如因为不同缓存之间的条件或key表达式不同。@Caching允许在同一个方法上使用多个嵌套的@Cacheable,@CachePut和@CacheEvict:

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

1.5、@CacheConfig annotation

示例;

@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {

    @Cacheable
    public Book findBook(ISBN isbn) {...}
}

  @CacheConfig是一个类级注释,允许共享缓存名称,自定义KeyGenerator,自定义CacheManager以及最终的自定义CacheResolver。将该注释放在类上不会启用任何缓存操作。

  操作级定制将始终覆盖@CacheConfig上的定制集。这给每个缓存操作三个级别的自定义:

全局配置,可用于CacheManager,KeyGenerator
在类级别上,使用@CacheConfig
在操作层面

1.6、启用注解

  需要注意的是,尽管声明缓存注释并不会自动触发它们的操作 - 就像Spring中的许多事情一样,该功能必须声明启用(这意味着如果您怀疑缓存是责任,您可以通过仅删除一个配置行而不是您的代码中的所有注释来禁用它)。要启用缓存注释,请将注释@EnableCaching添加到其中一个@Configuration类中:

@Configuration
@EnableCaching
public class AppConfig {
}

  或者,对于XML配置,使用缓存:注释驱动的元素:

<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.xsd">

        <cache:annotation-driven />

</beans>

  cache:annotation-driven元素和@EnableCaching注解都允许指定各种选项,以影响缓存行为通过AOP添加到应用程序的方式。该配置有意与@Transactional的配置类似:

注意:用于处理缓存注释的默认建议模式是“代理”,它允许仅通过代理拦截调用;相同类的本地方法间调用不能被这种方式拦截。对于更高级的拦截模式,考虑切换到“aspectj”模式并结合编译时或加载时编织。

  使用Java配置的高级定制需要实现CachingConfigurer

缓存注释设置

XML Attribute Annotation Attribute Default Description

cache-manager

N/A (See CachingConfigurerjavadocs)

cacheManager

Name of cache manager to use. A default CacheResolver will be initialized behind the scenes with this cache manager (or `cacheManager`if not set). For more fine-grained management of the cache resolution, consider setting the 'cache-resolver' attribute.

cache-resolver

N/A (See CachingConfigurerjavadocs)

SimpleCacheResolver using the configured cacheManager.

The bean name of the CacheResolver that is to be used to resolve the backing caches. This attribute is not required, and only needs to be specified as an alternative to the 'cache-manager' attribute.

key-generator

N/A (See CachingConfigurerjavadocs)

SimpleKeyGenerator

Name of the custom key generator to use.

error-handler

N/A (See CachingConfigurerjavadocs)

SimpleCacheErrorHandler

Name of the custom cache error handler to use. By default, any exception throw during a cache related operations are thrown back at the client.

mode

mode

proxy

The default mode "proxy" processes annotated beans to be proxied using Spring’s AOP framework (following proxy semantics, as discussed above, applying to method calls coming in through the proxy only). The alternative mode "aspectj" instead weaves the affected classes with Spring’s AspectJ caching aspect, modifying the target class byte code to apply to any kind of method call. AspectJ weaving requires spring-aspects.jar in the classpath as well as load-time weaving (or compile-time weaving) enabled. (See Spring configuration for details on how to set up load-time weaving.)

proxy-target-class

proxyTargetClass

false

Applies to proxy mode only. Controls what type of caching proxies are created for classes annotated with the @Cacheable or @CacheEvict annotations. If the proxy-target-class attribute is set to true, then class-based proxies are created. If proxy-target-class is false or if the attribute is omitted, then standard JDK interface-based proxies are created. (See Proxying mechanismsfor a detailed examination of the different proxy types.)

order

order

Ordered.LOWEST_PRECEDENCE

Defines the order of the cache advice that is applied to beans annotated with @Cacheableor @CacheEvict. (For more information about the rules related to ordering of AOP advice, see Advice ordering.) No specified ordering means that the AOP subsystem determines the order of the advice.

  
  <cache:annotation-driven />仅在它定义的相同应用程序上下文中寻找@Cacheable / @CachePut / @CacheEvict / @缓存bean。如果您将<cache:annotation-driven />放入DispatcherServlet的WebApplicationContext中,它只会检查控制器中的bean,而不是您的服务。
  方法可见性和缓存注释:使用代理时,应将缓存注释仅应用于具有公开可见性的方法。如果您使用这些注释注释受保护的,私有的或包可见的方法,则不会引发错误,但注释的方法不会显示已配置的缓存设置。如果您需要注释非公共方法,因为它会更改字节码本身,请考虑使用AspectJ(请参见下文)。
  Spring建议您仅使用@Cache *注释来注释具体类(以及具体类的方法),而不是注释接口。您当然可以将@Cache *注释放置在一个接口(或一个接口方法)上,但是这只能在您使用基于接口的代理时使用。
  事实上java注解不是继承自接口,意味着如果您使用的是基于类的代理(proxy-target-class =“true”)或基于织造的方面(mode =“aspectj”),那么代理和编织基础架构将无法识别缓存设置,并且该对象不会被包装在缓存代理中,这肯定会很糟糕。
  在代理模式下(这是默认模式),只有通过代理进入的外部方法调用才会被拦截。这意味着自调用实际上是目标对象内调用目标对象的另一个方法的方法,在运行时不会导致实际的缓存,即使被调用的方法标记为@Cacheable - 考虑在这种情况下使用aspectj模式。此外,代理必须完全初始化以提供预期的行为,因此您不应该在初始化代码中依赖此功能,即@PostConstruct。

1.7、自定义注解

  自定义注释和AspectJ:此功能只能使用基于代理的方法直接使用,但可以通过使用AspectJ进行额外的工作来启用。

    Spring-aspects模块仅为标准注释定义了一个方面。如果您定义了自己的注释,则还需要为这些注释定义一个方面。检查AnnotationCacheAspect作为示例。

  缓存抽象允许您使用自己的注释来确定什么方法触发缓存填充或驱逐。这作为模板机制非常方便,因为它消除了重复缓存注释声明的需要(如果指定了key或条件,则特别有用)或者如果您的代码库中不允许使用外部导入(org.springframework)。类似于其他的构造型注释,@Cacheable,@CachePut,@CacheEvict和@CacheConfig可以用作元注释,这是可以注释其他注释的注释。换句话说,让我们用我们自己的自定义注释替换一个常见的@Cacheable声明:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(cacheNames="books", key="#isbn")
public @interface SlowService {
}

  上面,我们定义了我们自己的SlowService注释,它本身用@Cacheable注解 - 现在我们可以替换下面的代码:

@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

  使用

@SlowService
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

尽管@SlowService不是Spring注释,但容器会在运行时自动获取它的声明并理解其含义。请注意,如上所述,需要启用注解驱动的行为。

  

猜你喜欢

转载自www.cnblogs.com/bjlhx/p/9167660.html