前言
之前提到过在使用 Redis 发布订阅模式解决集群环境下 WebSocket 通讯问题的时候,遇到了在监听器中无法使用 @Autowired 注解注入 bean 的问题,百度查询了一下,有多种解决方案,这里记录一下我使用的方案。
原因分析
由于 Spring 启动对 IOC 容器初始化也是监听的 Servlet 的初始化之后才开始初始化,但是 Servlet 的初始化是由 Servlet 容器在启动时初始化的(一般我们使用的较多的就是 Tomcat),然后在初始化完 Servlet 之后在对过滤器&监听器进行初始化。这样就导致一个问题——由于监听器是由 Servlet 容器进行初始化的,他执行在 Spring IOC 容器初始化之前,导致我们自己本身定义的监听器不能被 Spring 初始化到 IOC 容器,就不能使用 Spring 的依赖注入特性了。
解决方案
使用 Spring 提供的 ApplicationContext 获取实例,不使用注解注入。ApplicationContext 是 Spring 继 BeanFactory 之外的另一个核心接口或容器,允许容器通过应用程序上下文环境创建、获取、管理 bean。
代码实现
封装了一个工具类,直接调用 getBean 方法即可。
/**
* 获取实例上下文
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
扩展
观察工具类代码,会发现 ApplicationContext 是一个静态变量,使用了 set 方法对 ApplicationContext 进行了初始化更新,但是 set 方法并不是静态方法。这样就会出现一个代码规范问题——不允许使用非静态方法更新静态字段,代码扫描也会给出相应提示: Make the enclosing method "static" or remove this set.
如果把 ApplicationContext 修改为非静态变量,那么 getBean 也要相应的修改为非静态方法,因为静态方法不能调用非静态变量。如果将 getBean 修改为非静态方法,监听器中就不能直接使用工具类名调用方法,使用起来很不方便,于是找了其他办法来解决这个问题,后面会单独写一篇文章来记录。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于