Кэширование остается одним из самых основных механизмов повышения производительности в любом приложении для чтения тяжелых баз данных. В выпуске 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/