本指南将指导您完成在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/
[ 转载请保留原文出处、译者和译文链接。]