Spring の @Cacheable キャッシュの使用方法のチュートリアル

1. @Cacheable はキャッシュの使用を指定します

コントローラーを定義し、メソッドにアノテーションを追加し@Cacheable、使用するキャッシュを構成します。たとえば、 myMapCache は 1 次キャッシュが Map であることを意味し、myRedisCache は 2 次キャッシュが Redis であることを意味します。そしてキャッシュキーを設定します。キーは SPEL 式で構成されており、Spring はそれを動的に解析してキャッシュ キーを生成できます。

ヒント: myMapCache と myRedisCache は、Spring キャッシュに挿入される名前です。

@RestController
public class CachingAnnoController {
    
    

	@Cacheable(cacheNames = {
    
    "myMapCache","myRedisCache"},key = "'test_'+#key")
	@RequestMapping("/cachingAnno")
	public String cachingAnno(String key,String value){
    
    
		System.out.println("查询数据库值 = " + value);
		return "value";
	}
}

2. @EnableCaching はキャッシュ機能をオンにします

@Cacheable アノテーションを使用したことのある人は、キャッシュ機能を有効にするには @EnableCaching アノテーションを渡す必要があることを知っています。コードは以下のように表示されます。

@ComponentScan(value = "com.gwm")
@Configuration
@EnableCaching
public class SpringConfig {
    
    

}

3. 使用する特定のキャッシュを導入します。キャッシュ インターフェイスを実装します。

上記の @EnableCaching と @Cacheable は Spring が提供する基本的なキャッシュ フレームワークであり、特定のキャッシュは自分で導入する必要があります。たとえば、ここでは MyMapCache クラスと MyRedisCache クラスの 2 つのキャッシュを定義します。次に、インターフェイスのメソッドを実装します。

Spring は標準化されたインターフェイスとして Cache を提供します。Spring は特定の実装を気にせず、自分で実装できます。ただし、Spring には、CaffeineCache、EhCacheCache、ConcurrentMapCache、JCacheCache など、いくつかのデフォルト実装もあります。

public class MyMapCache implements Cache {
    
    

	public static final Map<Object, Object> map = new ConcurrentHashMap<>();

	private String cacheName;

	public MyMapCache(String cacheName) {
    
    
		this.cacheName = cacheName;
	}

	@Override
	public String getName() {
    
    
		return cacheName;
	}

	@Override
	public Object getNativeCache() {
    
    
		return null;
	}

	@Override
	public ValueWrapper get(Object key) {
    
    
		System.out.println(">>>>>>我是 MyMapCache 缓存中的 get() 方法");
		Object o = map.get(key);
		if (Objects.nonNull(o)) {
    
    
			return new SimpleValueWrapper(o);
		}
		return null;
	}

	@Override
	public <T> T get(Object key, Class<T> type) {
    
    

		return (T)map.get(key);
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
    
    
		return (T)map.get(key);
	}

	@Override
	public void put(Object key, Object value) {
    
    
		System.out.println(">>>>>>我是 MyMapCache 缓存中的 put() 方法");
		map.put(key, value);
	}

	@Override
	public void evict(Object key) {
    
    
		map.remove(key);
	}

	@Override
	public void clear() {
    
    
		map.clear();
	}
}

MyRedisCache クラスの実装のコードは次のとおりです。

public class MyRedisCache implements Cache {
    
    

	private String cacheName;
	private RedisTemplate<Object,Object> redisTemplate;

	public MyRedisCache(String cacheName, RedisTemplate<Object, Object> redisTemplate) {
    
    
		this.cacheName = cacheName;
		this.redisTemplate = redisTemplate;
	}

	@Override
	public String getName() {
    
    
		return cacheName;
	}

	@Override
	public Object getNativeCache() {
    
    
		return this;
	}

	@Override
	public ValueWrapper get(Object key) {
    
    
		System.out.println(">>>>>>我是 MyRedisCache 缓存中的 get() 方法");
		Object o = redisTemplate.opsForValue().get(key);
		if (Objects.nonNull(o)) {
    
    
			return new SimpleValueWrapper(o);
		}

		return null;
	}

	@Override
	public <T> T get(Object key, Class<T> type) {
    
    
		return null;
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
    
    
		return null;
	}

	@Override
	public void put(Object key, Object value) {
    
    
		System.out.println(">>>>>>我是 MyRedisCache 缓存中的 put() 方法");
		redisTemplate.opsForValue().set(key,value);
		redisTemplate.expire(key, Duration.ofMillis(3000));
	}

	@Override
	public void evict(Object key) {
    
    
		redisTemplate.delete(key);
	}

	@Override
	public void clear() {
    
    
		redisTemplate.execute((RedisCallback<Object>) conn->{
    
    

			// 清空所有缓存数据,要格外注意这个操作,很危险
			conn.flushDb();

			return ">>>>>>flush db success!";
		});
	}
}

4. キャッシュ管理クラス - CacheManager インターフェイスを実装します。

カスタム キャッシュを定義した後は、ここだけでは機能しないため、Spring の標準インターフェイス CacheManager クラスを使用して、キャッシュ アスペクト ロジックにキャッシュを追加する必要があります。

たとえば、MyMapCache キャッシュ管理クラス MyMapCacheManager を実装するには、コードは次のようになります。

public class MyMapCacheManager implements CacheManager {
    
    

	@Override
	public Cache getCache(String name) {
    
    
		return new MyMapCache(name);
	}

	@Override
	public Collection<String> getCacheNames() {
    
    
		return Arrays.asList("myMapCache");
	}
}

MyRedisCache キャッシュ管理クラス MyRedisCacheManager を実装します。コードは次のとおりです。

public class MyRedisCacheManager implements CacheManager {
    
    

	@Override
	public Cache getCache(String name) {
    
    
		return new MyRedisCache(name,redisTemplate);
	}

	@Override
	public Collection<String> getCacheNames() {
    
    
		return Arrays.asList("myRedisCache");
	}
}

次に、構成エントリ クラスの @Bean を介して特定のキャッシュを参照します。コードは以下のように表示されます。

@Configuration
public class MyRedisMainConfig {
    
    

	@Resource
	private RedisTemplate<Object,Object> redisTemplate;

	@Bean
	public MyMapCache myMapCache() {
    
    
		MyMapCache myMapCache = new MyMapCache("myMapCache");
		return myMapCache;
	}
	
	@Bean
	public MyRedisCache myRedisCache() {
    
    
		MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);

		return myRedisCache;
	}
	
	@Bean
	public MyRedisCacheManager cacheManager() {
    
    
		MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
		return redisCacheManager;
	}
	
	// @Bean 
	public MyMapCacheManager cacheManager() {
    
    
		MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
		return redisCacheManager;
	}
	
}

ただし、特定の管理クラスを使用してキャッシュを導入すると、対応するキャッシュしか導入できないことが判明しました。たとえば、MyRedisCacheManager 管理クラスは MyRedisCache キャッシュのみを導入できますが、MyMapCache は導入できません。したがって、これは欠点です。ダブルバッファリングを使用したい場合はどうすればよいですか?

5. ダブルキャッシュの使用 - AbstractCacheManager 抽象クラスを実装します。

この抽象クラスは、すべてのキャッシュ インターフェイス実装クラスを取得できるloadCaches() メソッドを提供します。したがって、すべてのキャッシュはここで取得できます。そうすれば、間違いなくダブルバッファリングを使用できます。たとえば、MySimpleCacheManager クラスは次のコードで実装されます。

public class MySimpleCacheManager extends AbstractCacheManager implements ApplicationContextAware {
    
    

	private static final List<Cache> list = new ArrayList<>();

	private ApplicationContext context;
	/**
	 * 直接实现 AbstractCacheManager 抽象类的钩子方法,该类已经写好模版方法
	 * 当执行的时候,如果 MyGuavaCacheManager 管理类 @Bean 的话,就会勾到这个方法逻辑
	 * @return
	 */
	@Override
	protected Collection<? extends Cache> loadCaches() {
    
    
		return list;
	}

	@Override
	public void afterPropertiesSet() {
    
    
		Map<String, Cache> beansOfType = context.getBeansOfType(Cache.class);
		list.addAll(beansOfType.values());
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
		this.context = applicationContext;
	}
}

次に、エントリ クラスを構成します。コードは次のとおりです。

@Configuration
public class MyRedisMainConfig {
    
    

	@Resource
	private RedisTemplate<Object,Object> redisTemplate;

	@Bean
	public MyMapCache myMapCache() {
    
    
		MyMapCache myMapCache = new MyMapCache("myMapCache");
		return myMapCache;
	}
	
	@Bean
	public MyRedisCache myRedisCache() {
    
    
		MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);
		return myRedisCache;
	}
	
	@Bean
	public MySimpleCacheManager cacheManager(@Qualifier("myMapCache") MyMapCache myMapCache,
												 @Qualifier("myRedisCache") MyRedisCache myRedisCache,
												 @Qualifier("myGuavaCache") MyGuavaCache myGuavaCache) {
    
    
												 
		SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
		simpleCacheManager.setCaches(Arrays.asList(myMapCache,myRedisCache,myGuavaCache));
		return simpleCacheManager;
	}
}

最後に、キャッシュ管理クラス MySimpleCacheManager を注入することで、3 つのキャッシュを使用できるようになります。美しい。最終的に使用するには、パスします@Cacheable(cacheNames = {“myMapCache”,“myRedisCache”},key = “'test_'+#key”)myMapCache および myRedisCache キャッシュを使用できます。それでも myGuavaCache を使用する必要がある場合は、それを配列に直接追加するだけです。

6. RedisCacheManager 組み込みクラス

Redis キャッシュを使用する場合、Spring はすでにパッケージ化しているため、spring-data-redis パッケージを導入するだけで済みます。MyRedisCacheManager クラスを記述する必要はなく、Spring では Redis キャッシュを管理するための RedisCacheManager クラスがすでに提供されています。したがって、必要なのは Redis に接続できることだけです。次に、 @Bean を通じてRedisCacheManagerクラスを挿入して、Redis キャッシュを使用します。

おすすめ

転載: blog.csdn.net/qq_35971258/article/details/128724965