Spring中的aware接口详情
400
2022-09-17
springboot 缓存@EnableCaching实例
目录springboot 缓存@EnableCachingSpring @EnableCaching的工作原理
springboot 缓存@EnableCaching
很多时候系统的瓶颈都在一些比较复杂的IO操作,例如读取数据库,如果一些比较稳定的数据,一般的解决方案就是用缓存。spring boot提供了比较简单的缓存方案。只要使用 @EnableCaching即可完成简单的缓存功能。
缓存的实现有多种实现,ConcurentHashMapCache , GuavaCache, EnCacheCache等多种实现,spring boot 有默认的实现。本文不深入源码解读,首先用起来。
此处我们模拟要缓存的User
class User {
private Long id;
private String name;
// setter getter
}
然后我们业务对象:
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Component;
/**
* @author micro
* @date 2017年8月2日
* @description :
*/
@Component
@EnableCaching
public class UserDao {
private Map
@PostConstruct
public void init() {
//模拟数据库
userMap = new HashMap
userMap.put(1L, new User(1L,"micro1"));
userMap.put(2L, new User(2L, "micro2"));
}
@Cacheable("user") // 注解key属性可以执行缓存对象user(可以理解为一个map)的key
public User getUser(Long userId) {
System.out.println("查询数据库:userId ->" + userId);
return userMap.get(userId);
}
@Cacheable(value = "nameCache", key = "#name")
public User getUserByName(Long userId, String name) {
System.out.println("查询数据库:userId ->" + userId);
return userMap.get(userId);
}
@Cacheable("nameCache")
public User getUserByName(String name) {
System.out.println("查询数据库:userName : " + name);
for (Long k : userMap.keySet()) {
if (userMap.get(k).equals(name)) {
return userMap.get(k);
}
}
return null;
}
@CachePut("user") // 与Cacheable区别就是Cacheable先看缓存如果有,直接缓存换回,CachePut则是每次都会调用并且把返回值放到缓存
public User getUser2(Long userId) {
System.out.println("查询数据库:userId : " + userId);
return userMap.get(userId);
}
@CacheEvict("user")
public void removeFromCache(Long userId) {
return ;
}
}
然后我们编写启动类:
@SpringBootApplication
public class CacheTest implements CommandLineRunner {
@Autowired
private UserDao userDao;
public static void main(String[] args) {
new SpringApplication(CacheTest.class).run(args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("第一次查询");
System.out.println(userDao.getUser(1L));
System.out.println("第二次查询");
System.out.println(userDao.getUser(1L));
userDao.removeFromCache(1L);// 移除缓存
System.out.println("第三次查询");
userDao.getUser(1L);// 没有缓存了
System.out.println("--------");
// 测试不同的key缓存
userDao.getUserByName("micro1");
userDao.getUserByName(1L, "micro1");// 指定了参数name 为key 此次读取缓存
}
}
打印结果:
第一次查询
查询数据库:userId ->1
User@65da01f4
第二次查询
User@65da01f4
第三次查询
查询数据库:userId ->1
--------
查询数据库:userName : micro1
Spring @EnableCaching的工作原理
1、开发人员使用注解@EnableCaching
2、注解@EnableCaching导入CachingConfigurationSelector
3、CachingConfigurationSelector根据注解@EnableCaching 属性AdviceMode mode决定引入哪些配置类
PROXY : AutoProxyRegistrar,ProxyCachingConfiguration;
ASPECTJ : AspectJCachingConfiguration;
本文以mode=PROXY为例;
4、CachingConfigurationSelector导入AutoProxyRegistrar会确保容器中存在一个自动代理创建器(APC);
用于确保目标bean需要被代理时有可用的代理创建器
5、ProxyCachingConfiguration向容器定义如下基础设施bean
名称为org.springframework.cache.config.internalCacheAdvisor类型为BeanFactoryCacheOperationSourceAdvisor的bean
名称为cacheOperationSource类型为CacheOperationSource的bean
用于获取方法调用时最终应用的Spring Cache注解的元数据
名称为cacheInterceptor类型为CacheInterceptor的bean
一个MethodInterceptor,包裹在目标bean外面用于操作Cache的AOP Advice。
6、AutoProxyRegistrar在容器启动阶段对每个bean创建进行处理,如果该bean中有方法应用了Spring Cache注解,为其创建相应的代理对象,包裹上面定义的BeanFacgkBhlCvsqStoryCacheOperationSourceAdvisor bean;
7、使用了Spring Cache注解的bean方法被调用,其实调用首先发生在代理对象上,先到达cacheInterceptor,然后才是目标bean方法的调用;
cacheInterceptor既处理调用前缓存操作,也处理调用返回时缓存操作
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~