本指南将指导您完成在Spring所托管bean上启用缓存的过程。
您将构建一个应用程序,在一个简单的book repository中启用缓存。
与大多数[Spring 入门指南]一样( https://spring.io/guides),您可以从头开始并完成每个步骤,也可以绕过已经熟悉的基本设置步骤。 无论如何,你最终得到工作代码。
git clone https://github.com/spring-guides/gs-caching.git
gs-caching/initial
当你做完这一切, 你可以根据 gs-caching/complete
中的代码检查结果.
首先你设置一个基本的构建脚本。 你可以使用任何你喜欢的一个来构建项目,当使用Spring构建应用程序时,但是需要使用 Gradle 和 Maven 来写你的代码。 如果你不熟悉任何一个,请参考 使用Gradle构建Java项目 或 使用Maven构建Java项目 。
在您选择的项目目录中,创建以下子目录结构; 例如,在 nix 系统上使用`mkdir -p src / main / java / hello’:
└── src
└── main
└── java
└── hello
下面是 initial Gradle build file .
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-caching'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-cache")
}
Spring Boot gradle插件 提供了许多方便的功能:
public static void main()
方法来标记为可运行类。 首先你设置一个基本的构建脚本。 你可以使用任何你喜欢的一个来构建项目,当使用Spring构建应用程序,但是需要使用 Maven 来构建你的代码。 如果你不熟悉Maven,请参考 使用Maven构建Java项目 .
在您选择的项目目录中,创建以下子目录结构; 例如,在 nix 系统上使用`mkdir -p src / main / java / hello’:
└── src
└── main
└── java
└── hello
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-caching</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot Maven插件 提供了许多方便的功能:
public static void main()
方法来标记为可运行类。 首先,让我们为你的book创建一个非常简单的模型
src/main/java/hello/Book.java
package hello;
public classBook{
private String isbn;
private String title;
publicBook(String isbn, String title){
this.isbn = isbn;
this.title = title;
}
publicStringgetIsbn(){
return isbn;
}
publicvoidsetIsbn(String isbn){
this.isbn = isbn;
}
publicStringgetTitle(){
return title;
}
publicvoidsetTitle(String title){
this.title = title;
}
@Override
publicStringtoString(){
return "Book{" + "isbn='" + isbn + '/'' + ", title='" + title + '/'' + '}';
}
}
和该model的存储库:
src/main/java/hello/BookRepository.java
package hello;
public interfaceBookRepository{
BookgetByIsbn(String isbn);
}
您可以使用 Spring Data 在很多的SQL或NoSQL stores中提供repository仓库的实现,但是出于本指南的目的, 将使用模拟一些延迟(网络服务,慢延迟等)进行简单地的实现。
src/main/java/hello/SimpleBookRepository.java
package hello;
import org.springframework.stereotype.Component;
@Component
public classSimpleBookRepositoryimplementsBookRepository{
@Override
publicBookgetByIsbn(String isbn){
simulateSlowService();
return new Book(isbn, "Some book");
}
// Don't do this at home
privatevoidsimulateSlowService(){
try {
long time = 3000L;
Thread.sleep(time);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
simulateSlowService
是故意在每个 getByIsbn
调用中插入一个三秒延迟。 这是一个例子,稍后,你可以通过加入缓存来看到加速的效果。
接下来,连接repository库并使用它访问一些书。
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public classApplication{
publicstaticvoidmain(String[] args){
SpringApplication.run(Application.class, args);
}
}
@ SpringBootApplication是一个方便的注解,添加了以下所有内容:
main()方法使用Spring Boot的SpringApplication.run()方法来启动应用程序。你有注意到一行XML?没有 web.xml 文件。这个Web应用程序是100%纯Java,你不必处理配置任何管道或基础设施。
还有一个
CommandLineRunner
,注入 BookRepository
和 用不同的参数调用它几次。
src/main/java/hello/AppRunner.java
package hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public classAppRunnerimplementsCommandLineRunner{
private static final Logger logger = LoggerFactory.getLogger(AppRunner.class);
private final BookRepository bookRepository;
publicAppRunner(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
@Override
publicvoidrun(String... args)throwsException{
logger.info(".... Fetching books");
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("isbn-4567"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("isbn-4567"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
}
}
如果你尝试在此时运行应用程序,您会注意到它很慢,即使您几次检索完全相同的书。
2014-06-05 12:15:35.783 ... : .... Fetching books
2014-06-05 12:15:40.783 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2014-06-05 12:15:43.784 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2014-06-05 12:15:46.786 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
从时间戳可以看出,每本书花了大约三秒钟来检索,即使它是相同的标题被重复抓取。
让我们在你的SimpleBookRepository上启用缓存,这样书就会被缓存在 books
缓存中。
src/main/java/hello/SimpleBookRepository.java
package hello;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public classSimpleBookRepositoryimplementsBookRepository{
@Override
@Cacheable("books")
publicBookgetByIsbn(String isbn){
simulateSlowService();
return new Book(isbn, "Some book");
}
// Don't do this at home
privatevoidsimulateSlowService(){
try {
long time = 3000L;
Thread.sleep(time);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
您现在需要启用缓存注解的处理
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public classApplication{
publicstaticvoidmain(String[] args){
SpringApplication.run(Application.class, args);
}
}
@EnableCaching
注解触发检查并处理每个Spring bean用于存在对公共方法的缓存注解。如果找到这样的注解,则自动创建代理以拦截方法调用并相应地处理缓存行为。
缓存处理的相应注解是
Cacheable
,
CachePut
和
CacheEvict
.有关更多详细信息,可以参考javadocs和 文档
。
Spring Boot会自动配置一个合适的
CacheManager
,作为相关缓存。有关更多详细信息,请参阅 Spring Boot文档
。
我们的示例不使用特定的缓存库,因此我们的缓存存储是使用 ConcurrentHashMap
的简单回退。缓存抽象支持各种各样的缓存库,并完全符合JSR-107(JCache)。
您可以使用Gradle或Maven从命令行运行应用程序。 或者,您可以构建单个可执行文件,其中包含所有必需的依赖关系,类和资源,并运行它。 这使得在整个开发生命周期中,易于跨不同环境将服务作为应用程序进行发布,维护版本和部署等等。
如果您使用Gradle,可以使用 ./gradlew bootRun
运行应用程序。 或者你可以使用 ./gradlew build
来构建JAR文件。 然后可以运行JAR文件:
java -jar build/libs/gs-caching-0.1.0.jar
如果您使用Maven,可以使用 ./mvnw spring-boot:run
运行应用程序。 或者你可以用 ./mvnw clean package
构建JAR文件。 然后可以运行JAR文件:
java -jar target/gs-caching-0.1.0.jar
| ** | 上面的过程将创建一个可运行的JAR。 您也可以选择 build a classic WAR file |
|---|
现在缓存已启用,您可以再次执行它,并通过添加或不使用相同的isbn的额外调用查看差异。 你应该可以看到其产生明显的区别。
2016-09-01 11:12:47.033 .. : .... Fetching books
2016-09-01 11:12:50.039 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.044 .. : isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
This excerpt from the console shows that the first time to fetch each title took three seconds, but each subsequent call was near instantaneous.
从控制台的这段日志显示,第一次获取每个标题花了三秒钟,但每个后续的访问接近瞬间。
恭喜! 你刚刚通过Springcache在托管bean上启用了缓存。
翻译自: https://spring.io/guides/gs/caching/
[ 转载请保留原文出处、译者和译文链接。]