กลไกการแคชของสปริงมีความยืดหยุ่นมากและสามารถแคชวิธีถั่วหรือถั่วในภาชนะ ดังนั้นกลไกการแคชนี้สามารถแคชได้ในทุกระดับของการใช้งาน Javaee
ชั้นพื้นฐานของแคชสปริงจำเป็นต้องใช้งานด้วยความช่วยเหลือของเครื่องมือแคชอื่น ๆ เช่น EHCache (เครื่องมือแคชไฮเบอร์เนต) และชั้นบนใช้การเขียนโปรแกรม API แบบครบวงจร
ในการใช้แคชสปริงจำเป็นต้องมีสามขั้นตอนต่อไปนี้
ตัวอย่างเช่น
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <ehcache> <diskstore path = "java.io.tmpdir" /> <!-กำหนดค่าแคชเริ่มต้น-> MaxElementsOndisk = "10,000,000" DiskexpiRyThreadIntervalseconds = "120" MemoryStoreEvictionPolicy = "LRU"/> <!-กำหนดค่าแคชที่ชื่อผู้ใช้-> <cache name = "ผู้ใช้" MaxElementSInMemory = "10000" eternal = timetoliveseconds = "600" /> </ehcache>
ehcache.xml ข้างต้นกำหนดค่าสองพื้นที่แคช ถั่วในฤดูใบไม้ผลิจะถูกแคชในพื้นที่แคชเหล่านี้ โดยทั่วไปจะมีการกำหนดถั่วกี่ตัวในภาชนะฤดูใบไม้ผลิใน ehcache
จากนั้นกำหนดค่า Cache Manager ในไฟล์การกำหนดค่าสปริงดังต่อไปนี้โดยที่ถั่วตัวแรกเป็นถั่วจากโรงงานที่ใช้ในการกำหนดค่าแคชแมนเจอร์ของ Ehcache และถั่วตัวที่สองคือตัวจัดการแคชที่กำหนดค่าสำหรับแคชสปริงดังนั้นถั่วตัวแรกจะถูกฉีดเข้าไปในถั่วตัวที่สอง
<แคช: cache-driven cache-manager = "cachemanager" /> <!-กำหนดค่า ehcache cachemanager เพื่อระบุตำแหน่งของไฟล์ ehcache.xml ผ่านการกำหนดค่า-> <bean id = "ehcachemanager" p: configlocation = "classpath: ehcache.xml ehcache cachemanager ลงใน Cache Manager Bean-> <bean id = "cachemanager" p: cachemanager-ref = "ehcachemanager"> </ebean>
นี่คือการกำหนดค่าสปริงที่สมบูรณ์
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml xmlns: p = "http://www.springframework.org/schema/p" xmlns: cache = "http://www.springframework.org/schema/cache" xmlns: บริบท = XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http:/www.springframwork http://www.springframework.org/schema/cache/spring-cache-4.0.xsd http://www.springframework.org/schema/context <บริบท: Component-Scan base-package = "com.service" /> <cache: cache-driven cache-manager = "cachemanager" /> <!-กำหนดค่า ehcache cachemanager ระบุตำแหน่งของไฟล์ ehcache.xml ผ่านการกำหนดค่า-> P: Shared = "False"/> <!-กำหนดค่าตัวจัดการแคชที่ใช้ ehcache และฉีด cachemanager ของ Ehcache ลงใน Cache Manager Bean-> <bean id = "cachemanager" p: cachemanager-ref = "ehcachemanager">
ต่อไปนี้จะใช้ @Cacheable เป็นตัวอย่างเพื่อแสดงให้เห็นถึงการใช้สปริงตามแคช ehcache Cacheable ใช้เพื่อแก้ไขคลาสหรือวิธีการ หากคลาสได้รับการแก้ไขวิธีทั้งหมดในชั้นเรียนจะถูกแคช
แคชระดับชั้นเรียน
ตัวอย่างเช่นมีคลาสถั่วต่อไปนี้
@Service ("Userservice") @cacheable (value = "ผู้ใช้") คลาสสาธารณะ UserserViceImpl ใช้ UserserVice {@Override ผู้ใช้สาธารณะ GetUsersByNameAndage (ชื่อสตริงอายุ int) {System.out.println ( ส่งคืนผู้ใช้ใหม่ (ชื่ออายุ); } @Override ผู้ใช้สาธารณะ getAnotheruser (ชื่อสตริงอายุ int) {system.out.println ("การดำเนินการ getAnotheruser () .. "); ส่งคืนผู้ใช้ใหม่ (ชื่ออายุ); -แคชที่ใช้คลาสจะแคชทุกวิธีในชั้นเรียน หลังจากแคชโปรแกรมเรียกวิธีการใด ๆ ของอินสแตนซ์ของคลาสนี้ ตราบใดที่พารามิเตอร์ที่ผ่านนั้นเหมือนกันสปริงจะไม่ดำเนินการตามวิธี แต่จะค้นหาข้อมูลแคชโดยตรงตามพารามิเตอร์ที่ผ่าน!
ตัวอย่างเช่นใช้ข้อมูลที่แคชเช่นเดียวกับด้านล่าง
โมฆะคงที่สาธารณะ test2 () {ApplicationContext CTX = ใหม่ classPathxMlApplicationContext ("beans.xml"); UserserVice US = CTX.GETBEAN ("Userservice", UserserVice.class); ผู้ใช้ u1 = us.getusersbynameandage ("จางซาน", 50); // เนื่องจากพารามิเตอร์เดียวกันนี้ใช้เมื่อวิธีการ Userservice เรียกว่าเป็นครั้งที่สองวิธีการจริงจะไม่ถูกดำเนินการ // Spring จะค้นหาข้อมูลโดยตรงโดยพารามิเตอร์จากผู้ใช้แคช U2 = US.GetAnotherUser ("Zhang San", 50); System.out.println (u1 == u2); -ผลลัพธ์ผลลัพธ์
Getusersbynameandage () กำลังถูกดำเนินการ ..
จริง
อย่างที่คุณเห็น GetAnotheruser () ข้างต้นไม่ได้ถูกดำเนินการจริงเนื่องจากพารามิเตอร์ที่ผ่านจะเหมือนกับพารามิเตอร์ที่ส่งผ่านโดยวิธีก่อนหน้าดังนั้นสปริงโดยตรงมาจากข้อมูลพื้นที่แคช
นอกเหนือจากค่าแอตทริบิวต์ที่ต้องการแล้วคำอธิบายประกอบ @Cacheable ในคลาสถั่วด้านบนยังมีคีย์เงื่อนไขและเว้นแต่แอตทริบิวต์ สามสุดท้ายใช้ในการตั้งค่านโยบายการจัดเก็บสปริง สำหรับแคชที่ใช้คลาสสปริงใช้พารามิเตอร์ที่ส่งผ่านในเมธอดเป็นคีย์เพื่อค้นหาผลลัพธ์ในแคชโดยค่าเริ่มต้น
แน่นอนว่าเรายังสามารถปรับเปลี่ยนกลยุทธ์ของคีย์และให้สปริงทำตามมาตรฐานอื่น ๆ เช่นว่าพารามิเตอร์แรกนั้นเหมือนกับคีย์และค้นหาผลลัพธ์ในแคชหรือไม่
ปรับเปลี่ยนคลาสถั่วข้างต้นดังนี้
@Service ("ผู้ใช้") @cacheable (value = "ผู้ใช้", key = "#name") คลาสสาธารณะ UserserViceImpl ใช้ผู้ใช้ {@Override ผู้ใช้สาธารณะ GetUsersByNameAndage (ชื่อสตริงอายุ int) {หมายความว่าเราผ่านชื่อเดียวกันสปริงจะไม่ดำเนินการตามวิธี เมื่อชื่อแตกต่างกันจะมีการดำเนินการวิธีการเช่นเท่านั้น
โมฆะคงที่สาธารณะ test2 () {ApplicationContext CTX = ใหม่ classPathxMlApplicationContext ("beans.xml"); UserserVice US = CTX.GETBEAN ("Userservice", UserserVice.class); ผู้ใช้ u1 = us.getusersbynameandage ("จางซาน", 50); // หลังจากเปลี่ยนพารามิเตอร์คีย์ของ @Cacheable เป็น key = "#name" วิธีการต่อไปนี้จะสามารถดำเนินการได้ ผู้ใช้ u2 = us.getAnotheruser ("Li Si", 50); System.out.println (u1 == u2); - คุณจะเห็นได้ว่าเวลานี้มีการดำเนินการวิธี getAnotherUser() แล้ว
1 Getusersbynameandage () กำลังดำเนินการ ..
2 Getanotheruser () กำลังถูกดำเนินการ ..
3 เท็จ
นอกจากนี้เรายังสามารถตั้งค่าคุณสมบัติเงื่อนไขได้เช่น
@Service ("ผู้ใช้") @cacheable (value = "ผู้ใช้", เงื่อนไข = "#อายุ <100") ชั้นเรียนสาธารณะผู้ใช้งาน UserserViceImpl ใช้ UserserVice {@Override ผู้ใช้สาธารณะ GetUsersByNameAndage (ชื่อสตริงอายุ int) {ดังนั้นสำหรับรหัสต่อไปนี้จะไม่มีวิธีการแคช ฤดูใบไม้ผลิดำเนินการวิธีจริงเพื่อให้ได้ผลลัพธ์ทุกครั้ง
โมฆะคงที่สาธารณะ test2 () {ApplicationContext CTX = ใหม่ classPathxMlApplicationContext ("beans.xml"); UserserVice US = CTX.GETBEAN ("Userservice", UserserVice.class); ผู้ใช้ u1 = us.getusersbynameandage ("จางซาน", 500); ผู้ใช้ u2 = us.getAnotheruser ("Li Si", 500); System.out.println (u1 == u2); -ผลการดำเนินการ
Getusersbynameandage () กำลังถูกดำเนินการ ..
Getanotheruser () กำลังถูกดำเนินการ ..
เท็จ
แคชระดับเมธอดจะใช้ได้เฉพาะกับวิธีการเท่านั้น วิธีการที่แตกต่างกันสามารถตั้งค่าพื้นที่แคชที่ไม่จำเป็นเช่นสิ่งต่อไปนี้
@Service ("Userservice") คลาสสาธารณะ UserserViceImpl ใช้ UserserVice {@Cacheable ("Users1") @Override ผู้ใช้สาธารณะ GetUsersByNameAndage (ชื่อสตริงอายุ int) {System.out.println ( ส่งคืนผู้ใช้ใหม่ (ชื่ออายุ); } @Cacheable ("Users2") @Override ผู้ใช้สาธารณะ GetAnotherUser (ชื่อสตริงอายุ int) {System.out.println ("getAnotheruser () .. "); ส่งคืนผู้ใช้ใหม่ (ชื่ออายุ); -ใช้รหัสทดสอบต่อไปนี้
โมฆะคงที่สาธารณะ test2 () {ApplicationContext CTX = ใหม่ classPathxMlApplicationContext ("beans.xml"); UserserVice US = CTX.GETBEAN ("Userservice", UserserVice.class); // เป็นครั้งแรกที่วิธีการดำเนินการวิธีการจะถูกดำเนินการและผู้ใช้แคช U1 = us.getusersbynameandage ("จางซาน", 500); // แม้ว่าวิธีการต่อไปนี้จะผ่านพารามิเตอร์เดียวกันเนื่องจากสองวิธีนี้อยู่ในพื้นที่แคชที่แตกต่างกัน แต่ไม่สามารถใช้ข้อมูลแคชได้ ผู้ใช้ u2 = us.getAnotheruser ("Zhang San", 500); System.out.println (u1 == u2); // ข้างต้นได้รับการแคชแล้วและจะไม่ถูกประหารที่นี่ ใช้แคชโดยตรง ผู้ใช้ u3 = us.getAnotheruser ("Zhang San", 500); System.out.println (u3 == u2); -ผลการดำเนินการ
Getusersbynameandage () กำลังถูกดำเนินการ ..
Getanotheruser () กำลังถูกดำเนินการ ..
เท็จ
จริง
วิธีการที่แก้ไขโดย @cacheevict สามารถใช้เพื่อล้างแคชและคุณสมบัติต่อไปนี้สามารถระบุได้โดยใช้ @CacheEvict
Allentries ไม่ว่าจะล้างพื้นที่แคชทั้งหมด
ก่อนหน้านี้: ไม่ว่าจะล้างแคชก่อนที่จะดำเนินการวิธีการ ค่าเริ่มต้นคือการล้างมันหลังจากวิธีการถูกดำเนินการสำเร็จแล้ว
เงื่อนไขและคีย์ความหมายเดียวกับใน @Cacheable
การสาธิตต่อไปนี้เป็นเรื่องง่าย
@Service ("Userservice")@cacheable ("ผู้ใช้") คลาสสาธารณะ UserserViceImpl ใช้ Userservice {@Override ผู้ใช้สาธารณะ getUsersbynameAndage (ชื่อสตริงอายุ int) {system.out.println ( {system.out.println ("การดำเนินการ getAnotherUser () .. "); ส่งคืนผู้ใช้ใหม่ (ชื่อ, อายุ);} // ระบุแคชที่ชัดเจนตามชื่อและพารามิเตอร์อายุ @CacheEvict (value = "ผู้ใช้") void evictuser (ชื่อสตริง) {system.out.println (" การล้างข้อมูลที่แคชทั้งหมดในพื้นที่แคชผู้ใช้ @cacheeVict (value = "ผู้ใช้", allentries = true) โมฆะสาธารณะ evictall () {system.out.println ("-การล้างแคชทั้งหมด-");}}}ด้านล่างคือคลาสทดสอบ
โมฆะคงที่สาธารณะ test2 () {ApplicationContext CTX = ใหม่ classPathxMlApplicationContext ("beans.xml"); UserserVice US = CTX.GETBEAN ("Userservice", UserserVice.class); // ระบบจะแคชสองวิธีที่ผู้ใช้ u1 = us.getusersbynameandage ("Zhang San", 500); ผู้ใช้ u2 = us.getAnotheruser ("Li Si", 400); // เรียกเมธอด Evictuser () เพื่อล้างข้อมูลที่ระบุในบัฟเฟอร์ us.evictuser ("Li Si", 400); // ล้าง li si, 400 ก่อนที่ข้อมูลที่ส่งคืนโดยวิธีการต่อไปนี้จะถูกแคชอีกครั้งผู้ใช้ u3 = us.getAnotheruser ("Li Si", 400); System.out.println (US == U3); // FALSE // ข้อมูลของ Zhang San และ 500 ได้รับการแคชมาก่อนและวิธีการต่อไปนี้จะไม่ถูก execute อีกครั้งและข้อมูลในแคชจะถูกดึงโดยตรงผู้ใช้ U4 = US.GetAnotheruser ("Zhang San", 500); System.out.println (U1 == U4); // เอาต์พุตจริง // ล้างแคชทั้งหมด us.evictall (); // เนื่องจากแคชทั้งหมดได้รับการล้างรหัสต่อไปนี้จะถูก execute ผู้ใช้ u5 = us.getAnotheruser ("จางซาน", 500) ผู้ใช้ u6 = us.getAnotheruser ("Li Si", 400); System.out.println (u1 == u5); // เอาต์พุต System.out.println (u3 == u6); // เอาต์พุตเท็จ}ผลการดำเนินการ
Getusersbynameandage () กำลังถูกดำเนินการ ..
Getanotheruser () กำลังถูกดำเนินการ ..
-การล้างแคชที่สอดคล้องกับ Li Si, 400-
Getanotheruser () กำลังถูกดำเนินการ ..
เท็จ
จริง
-ล้างแคชทั้งหมด-
Getanotheruser () กำลังถูกดำเนินการ ..
Getanotheruser () กำลังถูกดำเนินการ ..
เท็จ
เท็จ
ข้างต้นเป็นเรื่องเกี่ยวกับรหัสตัวอย่างกลไกการแคชฤดูใบไม้ผลิในบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!