Кэширование остается одним из самых основных механизмов повышения производительности в любом приложении для чтения тяжелых баз данных. В выпуске Spring 3.1 появилась отличная новая функция под названием Cache Abstraction . Spring Cache Abstraction предоставляет разработчикам приложений простой, прозрачный и несвязанный способ реализации любого решения для кэширования. Memcached — одна из самых популярных систем распределенного кэширования, используемая в приложениях. В этом посте мы сосредоточимся на том, как интегрировать memcached в приложения с поддержкой Spring. Поскольку Spring напрямую поддерживает только Ehcache и ConcurrentHashMap, мы обратимся к сторонней библиотеке Simple Spring Memcache для использования возможностей абстракции кеширования Spring .
Получение кода
Код для этого урока может быть загружен из следующего местоположения SVN. https://www.assembla.com/code/weblog4j/subversion/nodes/24/SpringDemos/trunk Чтобы учебник работал, создайте следующую таблицу в своей базе данных. Затем измените источник данных в springcache.xml.
|
1
2
3
4
5
6
7
8
9
|
CREATE TABLE IF NOT EXISTS `adconnect`.`books` ( `book_id` INT NOT NULL AUTO_INCREMENT , `book_name` VARCHAR(500) NULL , `book_author` VARCHAR(500) NULL , `category` VARCHAR(500) NULL , `numpages` INT NULL , `price` FLOAT NULL , PRIMARY KEY (`book_id`) )ENGINE = InnoDB; |
Шаги интеграции
1. Зависимости — я также предполагаю, что у вас есть спящий режим, пружина и логи. Так что для загрузки зависимостей SSM добавьте следующее в свой POM. Для полного набора зависимостей, пожалуйста, скачайте проект с SVN URL выше.
|
01
02
03
04
05
06
07
08
09
10
11
|
<dependency> <groupId>com.google.code.simple-spring-memcached</groupId> <artifactId>spring-cache</artifactId> <version>3.1.0</version></dependency><dependency> <groupId>com.google.code.simple-spring-memcached</groupId> <artifactId>xmemcached-provider</artifactId> <version>3.1.0</version></dependency> |
2. Включить кэширование — чтобы включить кэширование в приложении Spring, добавьте следующее в свой контекст Spring xml.
|
1
|
<cache:annotation-driven/> |
3. Настройте Spring для включения кэширования на основе Memcached — добавьте следующее в свой контекст приложения xml.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<bean name="cacheManager" class="com.google.code.ssm.spring.SSMCacheManager"> <property name="caches"> <set> <bean class="com.google.code.ssm.spring.SSMCache"> <constructor-arg name="cache" index="0" ref="defaultCache"/> <!-- 5 minutes --> <constructor-arg name="expiration" index="1" value="300"/> <!-- @CacheEvict(..., "allEntries" = true) doesn't work --> <constructor-arg name="allowClear" index="2" value="false"/> </bean> </set> </property> </bean><bean name="defaultCache" class="com.google.code.ssm.CacheFactory"> <property name="cacheName" value="defaultCache"/> <property name="cacheClientFactory"> <bean name="cacheClientFactory" class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/> </property> <property name="addressProvider"> <bean class="com.google.code.ssm.config.DefaultAddressProvider"> <property name="address" value="127.0.0.1:11211"/> </bean> </property> <property name="configuration"> <bean class="com.google.code.ssm.providers.CacheConfiguration"> <property name="consistentHashing" value="true"/> </bean> </property></bean> |
SSMCacheManager расширяет org.springframework.cache.support.AbstractCacheManager — это абстрактный класс и менеджер для основного кэша.
SSMCache реализует org.springframework.cache.Cache — это фактическая оболочка вокруг базового API клиента кеша.
4. Кэширование на основе аннотаций. Spring использует аннотации для пометки метода, которым он должен управлять с помощью кеша. Это аннотации, определенные в рамках весеннего кэширования.
- @Cacheable — эта аннотация используется для пометки метода, результаты которого должны быть кэшированы. Если вызывается кешируемый метод, то Spring сначала проверяет, кэширован ли результат метода или нет. Если он присутствует в кеше, то результат извлекается оттуда, иначе выполняется вызов метода.
- @CachePut — Методы, помеченные аннотациями кэш-памяти, всегда запускаются, а их результаты помещаются в кэш. Не следует размещать аннотации Cacheput и Cacheable на одном и том же методе, поскольку они ведут себя по-разному. Cacheput приводит к тому, что метод выполняется все время, а кешируемые результаты — к выполнению метода только один раз
- @CacheEvict — эта аннотация приводит к удалению объектов из кэша. Это обычно используется, когда объект результата обновляется, поэтому старый объект из кэша необходимо очистить.
- @Caching — эта аннотация используется, если в метод нужно добавить несколько аннотаций одного типа.
@Cacheable Demo
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@Cacheable(value = "defaultCache", key = "new Integer(#book_id).toString().concat('.BookVO')") public BookVO get(int book_id) throws Exception { BookVO bookVO = null; try{ Query query = getSession().createQuery("from BookVO bookVO where bookVO.book_id=:book_id"); query.setLong("book_id", book_id); bookVO = (BookVO)query.uniqueResult(); }catch(HibernateException he){ log.error("Error in finding a bookVO : " + he); throw new Exception("Error in finding adPicVO by book_id for book_id : " + bookVO, he); } return bookVO; } |
Обратите внимание на ключевой атрибут аннотации. Это пример Spring Expression Language . Вы можете использовать SePL для создания ключа memcache в соответствии с вашими требованиями. В этом примере я хочу ключ, который должен иметь форму <book_id> .BookVO.
Другой пример. Допустим, я хочу сохранить список bookVO от данного автора. В этом случае я могу использовать уникальный ключ в форме <author_name> .BookVOList, поэтому для этого я могу использовать следующий ключ.
|
1
2
|
@Cacheable(value = "defaultCache", key = "#author.concat('.BookVOList')") public List<BookVO> getList(String author) throws Exception { |
@CachePut Demo
|
01
02
03
04
05
06
07
08
09
10
11
12
|
@CachePut(value = "defaultCache", key = "new Integer(#bookVO.book_id).toString().concat('.BookVO')") public BookVO create(BookVO bookVO) throws Exception { try{ getSession().save(bookVO); getSession().flush(); }catch(HibernateException he){ log.error("Error in inserting bookVO : " + he); throw new Exception("Error in inserting bookVO", he); } return bookVO; } |
CachePut может использоваться при вставке данных, когда вставленные данные могут быть помещены в кеш после того, как вставка сделана
@CacheEvict Демо
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
@CacheEvict(value = "defaultCache", key = "new Integer(#bookVO.book_id).toString().concat('.BookVO')") public BookVO update(BookVO bookVO) throws Exception { try{ Query query = getSession().createQuery("update BookVO bookVO set bookVO.book_name=:book_name, bookVO.book_author=:book_author,bookVO.category=:category,bookVO.numpages=:numpages,bookVO.price=:price " + "where bookVO.book_id=:book_id"); query.setString("book_name", bookVO.getBook_name()); query.setString("book_author", bookVO.getBook_author()); query.setString("category", bookVO.getCategory()); query.setInteger("numpages", bookVO.getNumpages()); query.setFloat("price", bookVO.getPrice()); query.setLong("book_id", bookVO.getBook_id()); query.executeUpdate(); }catch(HibernateException he){ log.error("Error in updating bookVO : " + he); throw new Exception("Error in updating bookVO", he); } return bookVO; } |
Ресурсы
- https://code.google.com/p/simple-spring-memcached/
- http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/cache.html
- http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/expressions.html
- http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/index.html?org/springframework/cache/CacheManager.html
- http://doanduyhai.wordpress.com/2012/07/01/cache-abstraction-in-spring-3/
- http://viralpatel.net/blogs/cache-support-spring-3-1-m1/