SpringBoot+SpringCache+Redis補充

這裏新增長一個例子:java

`spring

package com.atguigu.cache.service;

import com.atguigu.cache.bean.Employee;
import com.atguigu.cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

@CacheConfig(cacheNames = "emp")
[@Service](https://my.oschina.net/service)
public class EmployeeService {
	@Autowired
	EmployeeMapper employeeMapper;

	/**
	 * 將方法的運行結果進行緩存,之後在要相同的數據,直接從緩存中獲取,不用調用方法
	 *
	 * CacheManager管理多個Cache組件的,對緩存的真正CRUD操做在Cache組件中,每個緩存
	 * 組件有本身惟一一個名字
	 *
	 * 幾個屬性:
	 *   cacheName/value:指定緩存組件的名字;將方法的返回結果放在哪一個緩存中,是數組的方式,能夠指定多個緩存;
	 *   key:緩存數據使用的key,能夠用它來指定,默認是使用方法參數的值 1-方法的返回值
	 *     編寫SqEL; #id,參數id的值  #a0  #p0  #root.args[0]
	 *   keyGenerator:key的生成器;能夠本身指定key的生成器的組件
	 *     key/keyGenerator:二選一使用
	 *     cacheManager:緩存管理器;或者cacheResolver指定獲取解析器
	 *     condition:指定符合條件的狀況下才緩存;
	 *       condition="#id>0"
	 *       condition="#a0>1"l;第一個參數的值>1 的時候才進行緩存
	 *       (a0等於arg[0])
	 *     unless:否認緩存;當unless指定的條件爲true,方法的返回值就不會被緩存;能夠
	 *     獲取到結果進行判斷unless="#a0==2":若是第一參數的值是2,結果不緩存
	 *     sync:是否使用異步模式:異步模式不支持unless
	 *
	 * 原理:
	 *   1.緩存的自動配置類;CacheAutoConfiguration
	 *   2.緩存的配置類
	 *   org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
	 *   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默認】
	 *   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
	 *   3.哪一個配置類生效; SimpleCacheConfiguration
	 *
	 *   4.給容器中註冊了一個CacheManager、ConcurrentMapCacheManager
	 *   5.能夠獲取和建立ConcurrentMapCache類型的緩存組件;他的做用將數據保存在ConcurrentMap中;
	 *
	 *   運行流程:
	 *   @Cacheable:
	 *   1.方法運行以前,先去查詢Cache(緩存組件),按照cacheNames指定的名字獲取;
	 *     (CacheManager先獲取相應的緩存),第一次獲取緩存若是沒有Cache組件會自動建立,
	 *   2.去Cache中查找緩存的內容,使用一個key,默認就是方法的參數;
	 *     key是按照某種策略生成的;默認是使用keyGenerator生成的,默認使用
	 *       SimpleKeyGenerator生成key的默認策略;
	 *         若是沒有參數;key=new SimpleKey();
	 *         若是有一個參數,key=參數的值
	 *         若是有多個參數:key=new SimpleKey(params);
	 *   3.沒有查到緩存就調用目標方法;
	 *   4.將目標方法的緩存結果,放進緩存中
	 *
	 *   @Cacheable標註的方法執行以前先來檢查緩存中有沒有這個數據,默認按照參數的值做爲key去查詢緩存,
	 *   若是沒有就運行方法並將結果放入緩存,之後再來調用就能夠直接使用緩存中的數據
	 *
	 *   核心:
	 *     1)、使用CacheManager【ConcurrentMapCacheManager】按照名字獲得Cache【ConcurrentMapCache】組件
	 *     2)、key使用keyGenerator生成的,默認是SimpleKeyGenerator
	 * @param id
	 * @return
	 */
	@Cacheable(value = {"emp"}/*,keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#a0==2"*/)
	public Employee getEmp(Integer id){
		System.out.println("查詢"+id+"號員工");
		Employee emp=employeeMapper.getEmpById(id);
		return emp;
	}

	/**
	 * @CachePut:即調用方法,又更新緩存數據:同步更新緩存 注意key要相同
	 * 修改了數據庫的某個數據,同時更新緩存;
	 * 運行時機:
	 *   一、先調用目標方法
	 *   二、將目標方法的結果緩存起來
	 *
	 * 測試步驟:
	 *   一、查詢1號員工;查到的結果會放在緩存中
	 *          key:1  value: lastName:張三
	 *   二、之後查詢仍是以前的結果
	 *   三、更新1號員工;【LastName:zhangsan:gender:0】
	 *          將方法的返回值也放進緩存了;
	 *          key: 傳入的employee對象 值:返回employee對象;
	 *   四、查詢1號員工?
	 *     應該是更新後的員工;
	 *       key = "#employee.id":使用傳入的參數的員工的id;
	 *       key = "#result.id";使用返回後的id
	 *              @Cacheable的key是不能用#result:
	 *              緣由:由於@Cacheable運行時機有兩個,一個是在運行方法以前
	 *                   一個是在運行方法以後,咱們要在方法一開始就獲得key,Put
	 *                   是先執行方法的,而able是先執行註解的
	 *     爲何是沒更新前的?【1號員工更新了,只是用的key不同】
	 */
	@CachePut(/*value = "emp",*/key = "#result.id")
	public Employee updateEmp(Employee employee){
		System.out.println("updateEmp:"+employee);
		employeeMapper.updateEmp(employee);
		return employee;
	}

	/**
	 * @CacheEvict:緩存清除
	 *   key:指定要清除的數據
	 *   allEntries=true:指定清除這個緩存中全部數據
	 *   beforeInvocation=false:緩存的清除是否在方法以前執行
	 *     默認表明緩存清除操做是在方法執行以後執行;若是出現異常緩存就
	 *     不會清除
	 *
	 *   beforeInvocation = true:
	 *     表明清除緩存操做是在方法運行以前執行,不管是否出現異常,緩存都清除
	 */
	@CacheEvict(/*value = "emp",*/beforeInvocation = true/*,key = "#id"*/)
	public void deleteEmp(Integer id){
		System.out.println("deleteEmp:"+id);
		/*employeeMapper.deleteEmpById(id);*/
	}

	/**
	 * @Caching 定義複雜的緩存規則
	 * 這裏意味着當你再用id或email調用時,則不須要再執行SQL語句
	 * @param lastName
	 * @return
	 */
	@Caching(
			cacheable = {
					@Cacheable(/*value = "emp",*/key = "#lastName")
			},
			put = {
					@CachePut(/*value = "emp",*/key = "#result.id"),
					@CachePut(/*value = "emp",*/key = "#result.email")//有@CachePut出現,下面的方法就必定會執行
			}
	)  //你依照id,郵箱,名字均可以得到該value
	public Employee getEmpByLastName(String lastName){
		System.out.println("複雜緩存");
		return employeeMapper.getEmpByLastName(lastName);
	}
}

` 這裏主要說了SpringCache註解的功能,而且更加詳細數據庫

可是我在另外一項目中使用這些註解卻出現了一些意外主要是由於key本來是String類型,可是我沒有將負值key爲id的屬性轉成String,這裏則說明有些須要轉型,有些則不須要:數組

`緩存

package cn.enilu.subor.service.system.impl;

import cn.enilu.subor.bean.entity.system.Video;
import cn.enilu.subor.dao.system.VideoRepository;
import cn.enilu.subor.service.system.VideoService;
import cn.enilu.subor.utils.factory.MutiStrFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

@CacheConfig(cacheNames = "video")
@Service
public class VideoServiceImpl implements VideoService {
	@Autowired
	private VideoRepository videoRepository;

	@Override
	public Page<Video> findAll(Pageable var1) {
		return videoRepository.findAll(var1);
	}

	@Override
	//@Cacheable(value = {"video"})
	public List<Video> findAll() {
		return videoRepository.findAll();
	}

	@Override
	@CachePut(key = "#video.id.toString()")
	public Video save(Video video) {
		return videoRepository.save(video);
	}

	@Override
	@CacheEvict(key = "#id.toString()")
	public void delete(Integer id) {
		System.out.println("dddddddddddddddddddd"+id);
		videoRepository.delete(id);
	}

	@CachePut(key = "#video.id.toString()")
	public void update(Video video){
		System.out.println("uuuuuuu");
		System.out.println("38218401779274902148901249012"+video);
		Integer videoId=video.getId();
		//String title=video.getTitle();
		String video_introduce=video.getVideoIntroduce();
		String video_type=video.getVideoType();
		Integer video_class=video.getVideoClass();
		//String video_url=video.getVideoUrl();
		//String img_title=video.getImgTitle();
		// String img_url=video.getImgUrl();
		videoRepository.updateById2(video_class,video_introduce,video_type,videoId);
	}

}

`app

這裏在附上註解的源碼,key的類型爲Stringless

`dom

package org.springframework.cache.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CachePut {
	@AliasFor("cacheNames")
	String[] value() default {};

	@AliasFor("value")
	String[] cacheNames() default {};

	String key() default "";

	String keyGenerator() default "";

	String cacheManager() default "";

	String cacheResolver() default "";

	String condition() default "";

	String unless() default "";
}

`異步

相關文章
相關標籤/搜索