(ソースコードの解析と)素人の言語との統合を使用した春のキャッシュ
個人的な開発環境
Java環境:Jdk1.8.0_60
コンパイラ:のIntelliJ IDEA 2019.1
springCache公式文書:https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/integration.html#cache
、春のキャッシュ抽象化
実際には、生成された背景SpringCache背景Springと多少似生成。コード、オブジェクトの作成や複雑な依存関係のJava EEフレームワーク肥大化し、非効率的で、低可観測するので、Springフレームワークが出てきた、本質的に、プロジェクトの全ては、Javaの背景春またはSpringBootから不可分である(さらにバネのパッケージングを簡素化) 。一般的には今のプロジェクトのキャッシュアプリケーションのより多くの種類も増加に直面し、高い同時実行性の問題、Springフレームワークには、キャッシュのサポートを完了するために、より便利で簡単な方法を持っている必要があります。
SpringCache自体も完了するために、特定のキャッシュ実装を満たすために必要なSpringCacheを使用するには、キャッシングシステムの抽象化を実現し、無特定のキャッシュ容量、です。
- キャッシュインターフェース仕様は、アセンブリキャッシュ、各種操作のセットを含むキャッシュとして定義されます。
- キャッシュインターフェースは、様々な春xxxCacheの実装を提供し; RedisCache、EhCacheCache、ConcurrentMapCacheのような場合。
第二に、重要な注意事項、パラメータ
名前 | 説明 |
---|---|
キャッシュ | キャッシュ・インタフェース、定義されたキャッシュ操作。そこ実現:ConcurrentMapCacheなどRedisCache、EhCacheCache、 |
CacheManager | キャッシュマネージャは、キャッシュ(キャッシュ)コンポーネントを管理します |
@Cacheable | 構成のための主な方法は、要求パラメータの方法に従ってキャッシュすることができます |
@CacheEvict | キャッシュを空に |
@CachePut | メソッドが呼び出されたことを確認し、その結果がキャッシュされている願っています。違いは@Cacheable各メソッドを呼び出しているかどうか、一般的更新で使用され |
@EnableCaching | オープン注釈ベースのキャッシング |
KeyGenerator | 鍵生成戦略キャッシュデータ |
シリアライズ | キャッシュのデータ値際に直列化戦略 |
@CacheConfig | ノートのこのクラスの統合キャッシュの構成プロパティ |
@キャッシング可能/ @ CachePut / @ CacheEvict主なパラメータ
名前 | 説明 |
---|---|
値 | @Cacheable(=「MyCacheという」値)または@Cacheable(値= {「cache1」、「cache2」} Spring構成ファイルで定義されたキャッシュ名は、少なくとも1つの例を指定する必要があります |
キー | @Cacheable(値=「testcache」、キー=「#IDは」):あなたはSPELが指定されていない場合は、デフォルトのパラメータは、すべての方法に従って例えば組み合わされて、表現に基づいて作成指定したい場合は、キャッシュのキーは、空にすることができます |
調子 | 緩衝液条件、空にすることができ、SpeIで書かれ、それが唯一のキャッシュ/キャッシュクリア例えば真であり、trueまたはfalseを返す:@Cacheable(値= "testcache"、状態= "#1 userName.lengthを()> 2") |
ない限り、 | ネガティブキャッシュ。条件の結果がTRUEである場合、それはキャッシュされません。@Cacheable(値= "testcache" = "#1 userName.length()> 2" でない限り) |
allEntries(@CacheEvict) | 例えば、すべてのキャッシュの内容をクリアするかどうか、デフォルトはfalse、trueを指定した場合、メソッドの呼び出しがされますすぐに明確なすべてのキャッシュ:@CachEvict(値=「testcache」、allEntries =真) |
beforeInvocation(@CacheEvict) | それは実行方法の前に空にされているかどうかの方法は、空のキャッシュ上で実行されていないときに、デフォルトでは、真で指定した実行メソッドが例外をスローした場合、それは例えばキャッシュをクリアしていない場合、デフォルトは、falseです:@ CachEvict(値= "testcache"、beforeInvocation =真) |
三、SPELコンテキストデータ
春のキャッシュSPELはテーブルが春の公式文書から直接引き出され、私たちが使用するデータのためのいくつかのコンテキストを提供します。
名前 | 場所 | 説明 | 例 |
---|---|---|---|
methodNameの | ルートオブジェクト | 現在の方法は、名前と呼ばれています | #1 root.methodname |
方法 | ルートオブジェクト | 現在のメソッドが呼び出されます | #1 root.method.name |
ターゲット | ルートオブジェクト | 現在のターゲット・オブジェクトがインスタンスと呼ばれています | #root.target |
targetClass | ルートオブジェクト | 現在のクラスは、ターゲットオブジェクトと呼ばれています | #1 root.targetClass |
引数 | ルートオブジェクト | パラメータのリストは、現在の法と呼ばれています | #1 root.args [0] |
キャッシュ | ルートオブジェクト | 現在のメソッド呼び出しは、キャッシュリストを使用します | #root.caches [0] .nameの |
引数名 | 実行コンテキスト | メソッドのパラメータは、findArtisan(職人業者)として、電流と呼ばれ、パラメータがartsian.id位によって得ることができます | #1 artsian.id |
結果 | 実行コンテキスト | (beforeInvocation =偽としてcacheEvictない限り決意を実行するための唯一の有効な方法、)メソッドの実行後に戻り値 | #結果 |
第四に、実際の
1.輸入依存度
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2. [スタート]クラスキャッシュのコメントを開く@EnableCaching
/**
* 1、开启基于注解的缓存 @EnableCaching
* 2、标注缓存注解即可
* @Cacheable
* @CacheEvict
* @CachePut
*/
@SpringBootApplication
@EnableCaching //开启缓存
public class CacheApplication{
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
3.キャッシュ@Cacheable
実行中のプロセス:
@Cacheable
最初に自動的に作成されたキャッシュCacheコンポーネントを取得していない場合はメソッドを実行する前に、cacheNames /値指定した名前に基づいて取得したクエリキャッシュ(キャッシュコンポーネント)、にアクセスしてください。
ソース分析:
public @interface Cacheable {
// cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存
@AliasFor("cacheNames")
String[] value() default {};
@AliasFor("value")
String[] cacheNames() default {};
// 缓存数据使用的key;可以用它来指定。默认是使用方法参数的值
String key() default "";
// key的生成器;可以自己指定key的生成器的组件id,key/keyGenerator:二选一使用;
String keyGenerator() default "";
// 指定缓存管理器;或者cacheResolver指定获取解析器 作用得到缓存集合
String cacheManager() default "";
String cacheResolver() default "";
// 条件符合则缓存,编写SpEL:condition = "#a0>1":第一个参数的值大于1的时候才进行缓存
String condition() default "";
// 条件符合则不缓存,编写SpEL:unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
String unless() default "";
// 是否使用异步模式,是否启用异步模式
boolean sync() default false;
}
ドリルビット:
@Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
public Employee getEmp(Integer id){
System.out.println("查询"+id+"号员工");
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
段ピット:
1、プロパティがvalue/cacheNames
必要であり、それはあなたの名前空間の一部に格納されているキャッシュを指定しています。
2、属性key
是使用的spEL表达式
注意
:踩坑,如果你把methodName
换成method
运行会报错,观察它们的返回类型,原因在于methodName
是String
而methoh
是Method
。
Employee
实体类一定要实现序列化public class Employee implements Serializable
,否则会报java.io.NotSerializableException
异常。
4.更新 @CachePut
@CachePut
既调用方法,又更新缓存数据;同步更新缓存。简单来说就是用户修改数据同步更新缓存数据。
源码分析:(皮一下,去事故与@Cacheable相同,不做过多解释了,狗头护体~~~)
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 "";
}
操练一下:
注意
该注解的value/cahceNames
和 key
必须与要更新的缓存相同,也就是与@Cacheable
相同。
@CachePut(value = "emp" ,key = "#employee.id")
public Employee updateEmp(Employee employee){
System.out.println("updateEmp:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
5.清除 @CacheEvict
@CachEvict
的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空 。
源码分析:
public @interface CacheEvict {
// 同上同上同上
@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 "";
// 指定清除这个缓存中所有的数据,示例:@CachEvict(value=”emp”,allEntries=true)
boolean allEntries() default false;
/*
* 示例: @CachEvict(value=”emp”,beforeInvocation=true)
* 代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
*
* 示例: @CachEvict(value=”emp”,beforeInvocation=false)(默认)
* 缓存的清除是否在方法之前执行 , 默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除
*/
boolean beforeInvocation() default false;
}
操练一下:
//方法调用后清空所有缓存
@CacheEvict(value="accountCache", allEntries=true)
public void deleteEmp() {
employeeMapper.deleteAll();
}
6.组合 @Caching
有时候我们可能组合多个Cache注解使用,此时就需要@Caching组合多个注解标签了。
源码分析:
public @interface Caching {
// 用于指定多个缓存设置操作
Cacheable[] cacheable() default {};
// 用于指定多个缓存更新操作
CachePut[] put() default {};
// 用于指定多个缓存失效操作
CacheEvict[] evict() default {};
}
操练一下
// @Caching 定义复杂的缓存规则
@Caching(
cacheable = {
@Cacheable(value="emp",key = "#lastName")
},
put = {
@CachePut(value="emp",key = "#result.id"),
@CachePut(value="emp",key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
7.全局配置 @CacheConfig
当我们需要缓存的地方越来越多,可以使用@CacheConfig(cacheNames = {"emp"})
注解来统一指定value
的值,这时可省略value
,如果你在你的方法依旧写上了value
,那么依然以方法的value
值为准。
源码分析:
public @interface Caching {
// 用于指定多个缓存设置操作
Cacheable[] cacheable() default {};
// 用于指定多个缓存更新操作
CachePut[] put() default {};
// 用于指定多个缓存失效操作
CacheEvict[] evict() default {};
}
操练一下:
@CacheConfig(cacheNames = {"emp"}, /*keyGenerator = "cacheKeyGenerator"*/)
public class EmployeeServiceImpl implements EmployeeService {
@Override
@Cacheable(/*value = ‘emp’*/ key = "targetClass + methodName +#p0")
public Employee getEmp(Integer id){
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
}
8.主键生成策略 keyGenerator
操练一下:
创建CacheConfig配置类
@Configuration
public class CacheConfig {
/**
* 生成缓存主键策略 (方法名+参数)
*
* @return KeyGenerator
*/
@Bean("cacheKeyGenerator")
public KeyGenerator keyGenerator() {
return (target, method, params) -> (method.getName() + " [ " + Arrays.asList(params) + " ]");
}
}
可以在@CacheConfig
指定生成策略,也可以在@Cacheable/@CachePut/@CacheEvict
指定key生成策略
@CacheConfig(cacheNames = {"emp"}, keyGenerator = "cacheKeyGenerator")
public class EmployeeServiceImpl implements EmployeeService {
@Override
@Cacheable(/*value = ‘emp’,keyGenerator = "cacheKeyGenerator"*/)
public Employee getEmp(Integer id){
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
}