1、pom文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
2、缓存配置
@Configuration public class AppConfig { @Autowired UserService userService; @Bean(name = "userCache") public LoadingCache<Integer,UserDTO> getUserInfo() { LoadingCache<Integer,UserDTO> userInfoCache = CacheBuilder.newBuilder() .expireAfterWrite(10,TimeUnit.SECONDS) .build(new CacheLoader<Integer, UserDTO>() { @Override public UserDTO load(Integer key) throws Exception { return userService.getUserInfoById(key); } }); return userInfoCache; } }
3、DTO 及 实现类
@Data @AllArgsConstructor @NoArgsConstructor public class UserDTO implements Serializable { private Integer id; private String name; }
public interface UserService { UserDTO getUserInfoById(Integer id); List<UserDTO> getAllUsers(); }
@Service public class UserServiceImpl implements UserService { @Override public UserDTO getUserInfoById(Integer id) { if (id == null) { return null; } if(id == 1) { return new UserDTO(1,"李1"); } else if (id == 2) { return new UserDTO(2,"李2"); } else { return new UserDTO(3,"李3"); } } @Override public List<UserDTO> getAllUsers() { return null; } }
4、调用
@RestController @RequestMapping("/guava") public class GuavaCacheController { @Autowired @Qualifier("userCache") LoadingCache<Integer,UserDTO> userCache; @GetMapping("/getUser") public UserDTO getUserId(Integer id) { UserDTO userDTO = null; try { userDTO = userCache.get(id); } catch (Exception e) { e.printStackTrace(); } return userDTO; } }
5、断点打在实现类上
第一次请求id =1 时 走断点
第一次请求id =3 时 走断点
第二次请求id=1 时 不走断点
过10s后请求 id =1,走断点
expireAfterWrite 与 refreshAfterWrite区别
expireAfterWrite
在缓存更新后某个时间失效缓存,这里Guava内部会对某个时间点失效的缓存做统一失效,只要有get访问任一key,就会失效当前时间失效的缓存,会移除当前key。所以这里也希望我们创建的缓存数据量不宜过大,使用guavaCache最好是设置一下maximumSize,避免出现内存溢出的情况。失效后需要获取新值才可会返回。
refreshAfterWrite
是指在创建缓存后,如果经过一定时间没有更新或覆盖,则会在下一次获取该值的时候,会在后台异步去刷新缓存,如果新的缓存值还没有load到时,则会先返回旧值。这里跟上面的expireAfterWrite不同的是,及时到了该刷新的时间,不会失效旧值和移除对应key。在后台异步刷新的过程中,如果当前是刷新状态,及时有其他线程访问到旧值,依然只有一个线程在更新,不会出现多个线程同时刷新同一个key的缓存。