妙用@Autowired实现对象的注入与封装改造RedisUtils

1. 改造之前的代码

        之间的代码注入方法直接声明了公共的静态字段, 所以不满足封装原则, 因为我可以在任意的地方给 redisTemplate 字段重新赋值, 可能会导致程序出错

妙用@Autowired实现对象的注入与封装改造RedisUtils_第1张图片

2. 改造之后的代码

        改造思路是为了满足封装原则

        1. RedisUtil 工具类, 里面提供静态方法, 需要在外部直接调用 RedisUtil.set() 方法或其他方法完成对 redis 的操作

        2. redisTemplate 需要封装到 RedisUtil 内部,  redisTemplate 必须是私有的, 不能通过外部传递, 阻止外部调用对 redisTemplate 重新赋值

        3. redisTemplate 必须是静态的, 因为操作 redis 的方法是静态的, 需要用 RedisUtil 类名直接调用

        4. RedisUtil 的构造器必须是私有的, 防止在外部创建对象, 如果需要创建对象, 这个对象必须是单例的

改造其实很简单, 依赖 @Autowired 注解

第一 : 私有化构造器, 防止在类的外部实例化, 当然你可以用反射, 但是即便用了反射创建了对象, 也没办法在外部调用私有静态字段和私有方法

第二 : redisTemplate 字段应该是私有的, 防止在外部重新赋值, 而且必须是静态的, 应为需要在静态的方法中使用

第三 : 由于 redisTemplate 字段是静态的, 没办法在字段上使用 @Autowired 注解, 所以需要提供一个方法, 在方法上使用 @Autowired 注解, 方法内部给静态字段赋值,  并且该方法需要是私有的, 也是为了防止在类的外部被调用

类中的 setRedisTemplate() 为什么会被调用不清楚的可以看下 @Autowired 的原理, 简单来说就是 :

        Spring 在通过 byName 的自动填充属性时流程是 :

                1.  找到所有set方法所对应的XXX部分的名字
                2.  根据XXX部分的名字去获取bean

        Spring 在通过 byType 的自动填充属性时流程是 :

                1.  获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean
                2.  如果找到多个,会报错。

相关源码体现 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

妙用@Autowired实现对象的注入与封装改造RedisUtils_第2张图片

 附上这个工具类的全代码

package com.kone.sp.common.redis2.utils;

import com.kone.sp.common.redis2.config.LettuceConnectionAutoConfiguration;
import com.kone.sp.common.redis2.config.RedisTemplateAutoConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author yukun.yan
 * @description RedisUtil redis缓存自动配置
 * @date 2023/5/5 10:15
 */
@Slf4j
@AutoConfigureAfter({RedisTemplateAutoConfiguration.class, LettuceConnectionAutoConfiguration.class})
public class RedisUtil {

    /**
     * 构造器应该是私有的
     */
    private RedisUtil() {

    }

    /**
     * 静态注入字段, 必须私有化, 满足封装原则
     */
    private static RedisTemplate redisTemplate;

    /**
     * 因为静态字段没办法直接使用 @Autowired 注入, 所以可以提供一个方法
     * 而且方法应该是私有的, 只能在类的内部调用, 防止重新给 redisTemplate 赋值
     */
    @Autowired
    private void setRedisTemplate(RedisTemplate redisTemplate) {
        RedisUtil.redisTemplate = redisTemplate;
    }

    /**
     * @param key 需要获取目标数据的唯一标识key
     * @return 返回key对应唯一的value
     */
    public static Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * @param key  指定redis key
     * @param time 设置过期时间  单位秒
     * @return 设置成功状态
     */
    public static Boolean expire(String key, long time) {
        return expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * @param key      指定redis key
     * @param time     设置过期时间
     * @param timeUnit 时间单位
     * @return 设置成功状态
     */
    public static Boolean expire(String key, long time, TimeUnit timeUnit) {
        return redisTemplate.expire(key, time, timeUnit);
    }

    /**
     * @param key 指定redis key
     * @return 当前key的过期时间 单位秒
     */
    public static long getExpire(String key) {
        return Optional.ofNullable(redisTemplate.getExpire(key, TimeUnit.SECONDS)).orElse(0L);
    }


    /**
     * @param key   所存储的 key值
     * @param value 所存储的 value值
     */
    public static void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * @param key   所存储的 key值
     * @param value 所存储的 value值
     * @param time  设置存储后过期时间 单位秒
     */
    public static void zset(String key, Object value, long time) {
        set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * @param key      所存储的 key值
     * @param value    所存储的 value值
     * @param time     设置存储后过期时间
     * @param timeUnit 时间单位
     */
    public static void set(String key, Object value, long time, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, time, timeUnit);
    }


    /**
     * 检查如果当前key不为存在则新增 存在则不改变已经有的值
     *
     * @param key   所存储的 key值
     * @param value 所存储的 value值
     * @return 返回是否修改当前key对应的value的状态结果
     */
    public static boolean setIfAbsent(String key, Object value) {
        return Optional.ofNullable(redisTemplate.opsForValue().setIfAbsent(key, value)).orElse(false);
    }

    /**
     * 检查如果当前key不为存在则新增 存在则不改变已经有的值
     *
     * @param key   所存储的 key值
     * @param value 所存储的 value值
     * @param time  设置存储后过期时间 单位秒
     * @return 返回是否修改当前key对应的value的状态结果
     */
    public static boolean setIfAbsent(String key, Object value, long time) {
        return setIfAbsent(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 检查如果当前key不为存在则新增 存在则不改变已经有的值
     *
     * @param key      所存储的 key值
     * @param value    所存储的 value值
     * @param time     设置存储后过期时间
     * @param timeUnit 时间单位
     * @return 返回是否修改当前key对应的value的状态结果
     */
    public static boolean setIfAbsent(String key, Object value, long time, TimeUnit timeUnit) {
        return Optional.ofNullable(redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit)).orElse(false);
    }


    /**
     * @param key 删除key
     */
    public static void delete(String key) {
        if (StringUtils.isEmpty(key)) {
            return;
        }
        redisTemplate.delete(key);
    }

    /**
     * 批量删除key
     *
     * @param keys 删除keys
     */
    public static void delete(Collection keys) {
        redisTemplate.delete(keys);
    }

    /**
     * 模糊删除
     *
     * @param likeKey 模糊删除的key, 比如"zhangsan*", 这时就会删除所有以zhangsan开头的key所对应的value
     */
    public static void deleteLike(String likeKey) {
        Set keys = keys(likeKey);
        if (keys != null && keys.size() > 0) {
            redisTemplate.delete(keys);
        }
    }

    /**
     * 模糊查询key
     *
     * @param likeKey 模糊删除的key, 比如"zhangsan*", 这时就会删除所有以zhangsan开头的key所对应的value
     */
    public static Set keys(String likeKey) {
        return redisTemplate.keys(likeKey);
    }

    /**
     * @param keys 批量获取 keys
     * @return 返回缓存的对象数据
     */
    public static List multiGet(Collection keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 获取两个集合的交集
     *
     * @param firstKey
     * @param firstKey
     * @return
     */
    public static Set intersect(String firstKey, String secondKey) {
        return redisTemplate.opsForSet().intersect(firstKey, secondKey);
    }

    /**
     * 获取多个变量的交集并保存到最后一个参数上
     *
     * @param keys
     * @param destKey
     */
    public static void intersectAndStore(List keys, String destKey) {
        log.info("redis intersectAndStore keys={} ", keys);
        String key = keys.get(0);
        keys.remove(key);
        log.info("redis intersectAndStore key={} otherKeys={} ", key, keys);
        redisTemplate.opsForSet().intersectAndStore(key, keys, destKey);
        expire(destKey, 20 * 60);
        keys.add(key);
    }

    public static void intersectAndStore(String key, String otherKey, String destKey) {
        redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey);
        expire(destKey, 20 * 60);
    }

    /**
     * 获取多个变量的合集并保存到最后一个参数上
     *
     * @param keys
     * @param destKey
     */
    public static void unionAndStore(List keys, String destKey) {
        log.info("redis unionAndStore keys={} ", keys);
        String key = keys.get(0);
        keys.remove(key);
        log.info("redis unionAndStore key={} otherKeys={} ", key, keys);
        redisTemplate.opsForSet().unionAndStore(key, keys, destKey);
        expire(destKey, 20 * 60);
        keys.add(key);
    }

    /**
     * 将求出来的差值元素保存
     *
     * @param key
     * @param otherKey
     * @param destKey
     */
    public static void differenceAndStore(String key, String otherKey, String destKey) {
        redisTemplate.opsForSet().differenceAndStore(key, otherKey, destKey);
        expire(destKey, 20 * 60);
    }

    /**
     * 存set
     *
     * @param key
     * @param setValue
     */
    public static void addSet(String key, Object... setValue) {
        redisTemplate.opsForSet().add(key, setValue);
        expire(key, 20 * 60);
    }

    /**
     * 获取set集合
     *
     * @param key
     * @return
     */
    public static Set getSet(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 取Set长度
     *
     * @param key
     * @return
     */
    public static long getSetSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 获取两个集合的并集
     *
     * @param firstKey
     * @param firstKey
     * @return
     */
    public static Set union(String firstKey, String secondKey) {
        return redisTemplate.opsForSet().union(firstKey, secondKey);
    }

    /**
     * 获取两个集合的差集
     *
     * @param firstKey
     * @param firstKey
     * @return
     */
    public static Set difference(String firstKey, String secondKey) {
        return redisTemplate.opsForSet().difference(firstKey, secondKey);
    }

    /**
     * 检查给定的元素是否在变量中
     *
     * @param key
     * @param value
     * @return
     */
    public static Boolean isMember(String key, String value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 获取变量中的值
     *
     * @param key
     * @return
     */
    public static Set members(String key) {
        return redisTemplate.opsForSet().members(key);
    }

}







你可能感兴趣的:(java,开发语言)