SpringBoot 注入RedisTemplate,解决无法注入问题

在项目中碰到需要在工具类中使用 RedisTemplate 的需求,一时想不到如何实现,通过搜索找到解决办法。同时也在 SpringContextHolder工具类 学习了 SpringContextHolder 的使用和实现。觉得RedisTemplate 自动注入失败的问题(redisTemplate == null) 一文总结的很好,所以转载在这(修改了其中一个认为有误地方)。


2022年01月04日更新

发现上面两链接都404了,脆弱的互联网。


更多关于Spring Boot RedisTemplate 集成和存取的使用,可以戳Spring笔记(11) Spring boot redis 的集成,开箱即用 Spring Data Redis

测试类中使用 RedisTemplate 对象

在测试中使用 RedisTemplate 不能直接用 @Resource或者@Autowired

原因:如果 Spring 容器中已经有了 RedisTemplate 对象了,在测试类中,这个自动配置的RedisTemplate 就不会再实例化。

解决方法:必须重新加载 Spring 容器获取 RedisTemplate 对象。

  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
        RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);

工具类中使用 RedisTemplate 对象

工具类中的对象或方法通常是静态的,所以必须用 static 修饰,而 RedisTemplate 不能用静态注入的方式。

解决办法:新建一个名为 SpringContextHolder 的工具类。

作用:以静态变量保存 Spring ApplicationContext ,可在任何代码任何地方任何时候取出 ApplicaitonContext。

注意:需在 Applicationcontext 中注册(把这个实例添加到 Spring IOC 容器里)或在类上使用注解Component,代码如下:

@Component
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
    private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    private static ApplicationContext applicationContext = null;

    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
                    ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
        }
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        logger.debug("清除SpringContextHolder中的ApplicationContext:"
                + applicationContext);
        applicationContext = null;
    }

    @Override
    public void destroy() throws Exception {
        SpringContextHolder.clearHolder();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringContextHolder.applicationContext != null) {
            logger.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
        }
        SpringContextHolder.applicationContext = applicationContext;
    }
}

使用获取

RedisTemplate redisTemplate = (RedisTemplate) SpringContextHolder.getBean("redisTemplate");

控制层 Controller 类中或 Service 使用RedisTemplate对象

直接@Resource或者@Autowired注入这个对象即可使用。

本文由老郭种树原创,转载请注明:https://guozh.net/springboot-injection-redistemplate/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注