今天在看 renren-security 源碼,發現能夠在配置文件中,動態的開啓/關閉redis緩存:java
renren: redis: open: false #是否開啓redis緩存 true開啓 false關閉
若是reren.redis.open=true,則會把sys_config表的數據同時保存到redisgit
若是reren.redis.open=false,則不會把sys_config表的數據同時保存到redis。面試
那這種功能是如何實現的呢?redis
首先,使用IDEA的Find in Path功能(個人快捷鍵爲)在源碼中查一下reren.redis.open這個配置:spring
源代碼:發現是在一個AOP切面中使用的:是對com.newbanker.common.utils.RedisUtils類(RedisUtils的源碼在下面)的全部方法作了攔截,json
若是reren.redis.open=true,則執行RedisUtils的目標方法(看上圖源碼,在第42行),不然不作任何處理。緩存
result = point.proceed(); // 上圖源碼42行:執行RedisUtils的目標方法
那咱們再看一下RedisUtils是幹啥的,源碼在下面,爲了便於閱讀,這裏先說一下RedisUtils這個類的重點:mybatis
package com.newbanker.common.utils; import com.alibaba.fastjson.JSON; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.SetOperations; import org.springframework.data.redis.core.ValueOperations; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; /** * Redis工具類 * * @author chenshun * @email sunlightcs@gmail.com * @date 2017-07-17 21:12 */ @Component public class RedisUtils { /** * 默認過時時長,單位:秒 */ public final static long DEFAULT_EXPIRE = 60 * 60 * 24; /** * 不設置過時時長 */ public final static long NOT_EXPIRE = -1; @Autowired private RedisTemplate redisTemplate; @Resource(name = "redisTemplate") private ValueOperations<String, String> valueOperations; @Resource(name = "redisTemplate") private HashOperations<String, String, Object> hashOperations; @Resource(name = "redisTemplate") private ListOperations<String, Object> listOperations; @Resource(name = "redisTemplate") private SetOperations<String, Object> setOperations; @Resource(name = "redisTemplate") private ZSetOperations<String, Object> zSetOperations; public void set(String key, Object value, long expire) { valueOperations.set(key, toJson(value)); if (expire != NOT_EXPIRE) { redisTemplate.expire(key, expire, TimeUnit.SECONDS); } } public void set(String key, Object value) { set(key, value, DEFAULT_EXPIRE); } public <T> T get(String key, Class<T> clazz, long expire) { String value = valueOperations.get(key); if (expire != NOT_EXPIRE) { redisTemplate.expire(key, expire, TimeUnit.SECONDS); } return value == null ? null : fromJson(value, clazz); } public <T> T get(String key, Class<T> clazz) { return get(key, clazz, NOT_EXPIRE); } public String get(String key, long expire) { String value = valueOperations.get(key); if (expire != NOT_EXPIRE) { redisTemplate.expire(key, expire, TimeUnit.SECONDS); } return value; } public String get(String key) { return get(key, NOT_EXPIRE); } public void delete(String key) { redisTemplate.delete(key); } /** * Object轉成JSON數據 */ private String toJson(Object object) { if (object instanceof Integer || object instanceof Long || object instanceof Float || object instanceof Double || object instanceof Boolean || object instanceof String) { return String.valueOf(object); } return JSON.toJSONString(object); } /** * JSON數據,轉成Object */ private <T> T fromJson(String json, Class<T> clazz) { return JSON.parseObject(json, clazz); } }
在使用時,只須要正常去編寫代碼,具體是否開啓redis,不在代碼中直接寫重複的if,把哪些重複的判斷redis是否開啓的判斷,放到AOP中:app
package com.newbanker.modules.sys.service.impl; import com.newbanker.common.utils.RedisUtils; import com.newbanker.modules.sys.dao.SysConfigDao; import com.newbanker.modules.sys.entity.SysConfigEntity; import com.newbanker.modules.sys.service.SysConfigService; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service("sysConfigService") public class SysConfigServiceImpl extends ServiceImpl<SysConfigDao, SysConfigEntity> implements SysConfigService { @Autowired private RedisUtils redisUtils; @Override @Transactional(rollbackFor = Exception.class) public void save(SysConfigEntity config) { // 保存數據到db baseMapper.insert(config); // 保存數據到redis redisUtils.set(config.getParamKey(), config.getParamValue()); } }
回想一下面試時,是否是被問到過:請說一下你對AOP的理解和使用?ok,上面說的這些,就是對AOP的使用的很好的案例。ide
另外:說一下個人感悟:就想標題同樣:《使用application.yaml配置開啓或關閉redis》,咱們在編寫代碼中,能夠把一些功能經過AOP和配置文件的方式,進行實現,可是具體是否啓用,能夠統一在AOP中進行判斷。雖然可使用以下方式進項啓用與否的判斷:
if (open) { // 保存數據到redis redisUtils.set(config.getParamKey(), config.getParamValue()); }
但若是有不少相似的判斷邏輯,確實應該使用AOP,避免在業務代碼中加入不少模板方法。
關於模板方法,能夠看: