Turn redis on or off using the AOP+application.yaml configuration item

Scene description

-- Watch it today renren-security Source code, found that redis caches can be dynamically turned on/off in the configuration file:

renren:
  redis:
    open: false #Whether to turn on redis cache true Turn on false Close

If reren.redis.open=true, the data from the sys_config table will also be saved to redis

If reren.redis.open=false, the data from the sys_config table will not be saved to redis at the same time.

So how does this work?

View Source

 

    reren.redis.open

First, use IDEA's Find in Path feature (my shortcut is) to check the reren.redis.open configuration in the source code:

Source code: Discovery is used in an AOP facet: intercepts all methods of the com.newbanker.common.utils.RedisUtils class (the source code for RedisUtils is below).

If reren.redis.open=true, execute the target method of RedisUtils (see source code, line 42) or do nothing else.

result = point.proceed(); //Source line 42 above: Target method to execute RedisUtils

 

 

    RedisUtils

Let's take a look at what RedisUtils does. The source code is below. To make it easier to read, here's the main point of the RedisUtils class:

  1. There is a comment on the RedisUtils class: @Component (Because it is an AOP facet, the target class must be a spring container managed class.If you don't understand it, take a look at AOP basics first.)
  2. All the methods below are for redis storage and reading (get method, set method, etc.)
  3. Here's the conclusion: Knowing these two points, AOP is blocking redis read-write operations, and only when reren.redis.open=true is configured will redis be read-write operations.
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 Tool class
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-07-17 21:12
 */
@Component
public class RedisUtils {
    /**
     * Default expiration time in seconds
     */
    public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
    /**
     * Do not set expiration time
     */
    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 Convert to JSON data
     */
    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 Data, to Object
     */
    private <T> T fromJson(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }
}

 

Use

When using, you only need to write code normally, whether to turn on redis, not to write duplicate if directly in the code, which duplicate judgments to determine whether redis are turned on, into AOP:

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) {
        // Save data to db
        baseMapper.insert(config);

        // Save data to redis
        redisUtils.set(config.getParamKey(), config.getParamValue());
    }

}

 

summary

Looking back at the interview, did you get asked: What is your understanding and use of AOP?ok, these are good examples of AOP use.

In addition: let me tell you what I think: Just like the title:'Use application.yaml configuration to turn redis on or off', we can write code to implement some functionality through AOP and configuration files, but whether it is enabled or not can be judged in AOP.Although you can use the following ways to determine whether an entry is enabled or not:

if (open) {
    //Save data to redis
    redisUtils.set(config.getParamKey(), config.getParamValue());
}

 

However, if you have a lot of similar logic, you should use AOP to avoid adding many template methods to your business code.

For template methods, you can see:

Keywords: Programming Redis JSON Spring Java

Added by xzazx on Sun, 19 May 2019 11:45:31 +0300