在项目中碰到需要在工具类中使用 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/