spring项目使用EMQX,使用@Autowired注入失败报错空指针问题记录
java客户端使用MQTT订阅消息大致流程
- 首先通过消息服务器节点的地址,new 一个MqttClient连接对象然后给MqttClient设置回调。
- 这里是通过new 一个MqttCallback对象(注入失败问题就在这) 来实现对topic中消息的监听和处理,所以服务端的处理心跳消息的主要业务逻辑均在MqttCallback实例中的messageArrived方法中。
- 建立连接。
- 订阅topic。
MQTTConnect部分代码
/**
* 客户端connect连接mqtt服务器
*
* @param mqttCallback 回调函数
**/
public void setMqttClient(MqttCallback mqttCallback) throws MqttException {
MqttConnectOptions options = mqttConnectOptions(USER_NAME, PASS_WORD);
mqttClient.setCallback(mqttCallback);
mqttClient.connect(options);
}
/**
* MQTT连接参数设置
*/
private MqttConnectOptions mqttConnectOptions(String userName, String passWord) throws MqttException {
mqttClient = new MqttClient(HOST, clientId, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(10);///默认:30
options.setAutomaticReconnect(true);//默认:false
options.setCleanSession(false);//默认:true
//options.setKeepAliveInterval(20);//默认:60
return options;
}
MQTTListener部分代码
/**
* 这里采用了自定义一个ApplicationListener监听类,
* 在onApplicationEvent()方法中执行连接mqtt服务和订阅主题。
**/
@Slf4j
@Component
public class MQTTListener implements ApplicationListener<ContextRefreshedEvent> {
private final MQTTConnect server;
@Autowired
public MQTTListener(MQTTConnect server) {
this.server = server;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
try {
// 连接mqtt服务
server.setMqttClient(new Callback(server));
// 订阅主题
server.sub("com/iot/init");
server.sub("com/iot/init1");
server.sub("com/iot/init2");
server.sub("com/iot/init3");
} catch (MqttException e) {
log.error(e.getMessage(), e);
}
}
}
问题分析
由于我们需要在消息监听回调中执行业务逻辑,比如根据消息中的某个字段使用mapper查询数据库。所以在Callback类中用@Autowired引入的项目中的serviceImpl。这里可以看到注入的serviceImpl出现了空指针。
问题原因
在MQTTListener中我们使用了new来创建CallBack这个bean,那么我们在CallBack这个类的示例中注入bean就会失败,出现null。
这里原因可能是new出来的实例对象不由spring管理,所以其内部注入的bean也就失败了。(这里如果说的不对,希望大佬不吝赐教)
解决方法
解决方法就是使用到服务的时候,动态去加载Bean。
- 使用applicationContext的getBean()方法在使用的地方动态注入,比如以下的方式。
dynamicRoutingDataSource = applicationContext.getBean(DynamicRoutingDataSource.class);
- 在MQTTListener设置回调CallBack类时,使用注入的CallBack类的Bean。
总结
在Spring项目中,尽量统一把bean交给Spring容器管理,少使用new创建实例对象。
参考
记一次Spring项目中使用@Autowired注入bean,使用时报空指针异常的问题
Spring @Autowired注入为null,空指针异常
spring项目使用EMQX,使用@Autowired注入失败报错空指针问题记录的更多相关文章
- 【Intellij idea】spring中@Autowired注入失败
@Autowired注入失败失败的解决办法? 现有的解决的方案是: 打开file-settings或者ctrl+alt+s -> Editor 然后在Inspections 点击搜索栏 输入Sp ...
- spring boot开发 @autowired注入失败
@autowired注入失败 会出现如下错误提示: 2018-05-28 08:39:41.857 INFO 8080 --- [ restartedMain] org.hibernate.Versi ...
- 160309、Spring AOP操作action时无法注入,报空指针错误
今天帮同事看个问题,action注入失败,代码没问题,主要是stuts2权限移交的问题,特此记录一下 Spring AOP操作action时无法注入,报NullPointer异常 当使用Spring ...
- Spring AOP操作action时无法注入,报NullPointer异常
Spring AOP操作action时无法注入,报NullPointer异常当使用Spring AOP对action层进行操作时,会出现注入失败的问题,出现空指针异常.原因是一般struts2+spr ...
- idea的service注入mapper报错
一.问题 idea的java项目中,service类中注入mapper报错 二.解决 方法1 在mapper类上加上 @Repository 注解即可,当然不加也行,程序也不回报错,是idea的误报 ...
- RedisCluster的rename机制失败报错,解决又是数据倾斜问题
需求说明:spring session中的用户session更新是更新key的名字,所以对于key的操作时需要用newkey 替换oldkey value值只允许存在一个,这里用到rename就很合适 ...
- sql注入之报错注入and boolean注入
1.sql注入之报错注入 正常传参,返回页面正常: 加入' 返回页面报错,出现"zhangsan"' 报错注入使用的函数 在这里我们使用 select updatexml(1,c ...
- Windows Essentials Movie Maker 安装失败报错 ——问题解决
Windows Essentials Movie Maker 安装失败报错: (软件包名: wlsetup-all.exe) 查到官方论坛给出了一些回复: https://social.technet ...
- laravel 项目表单中有csrf_token,但一直报错419错误 解决redis连接错误:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persi
laravel 项目表单中有csrf_token,但一直报错419错误,因为项目中使用到Redis缓存,在强制关闭Redis后出现的问题,查询laravel.log文件查找相关问题 安装redis后在 ...
- spring JMS在接收消息的时候总是报错
spring JMS在接收消息的时候总是报错 org.springframework.jms.UncategorizedJmsException: Uncategorized exception oc ...
随机推荐
- RocksDB-键值存储
存储和访问数百PB的数据是一个非常大的挑战,开源的RocksDB就是FaceBook开放的一种嵌入式.持久化存储.KV型且非常适用于fast storage的存储引擎. 传统的数据访问都是RPC, ...
- 加速 AI 训推:Lepton AI 如何构建多租户、低延迟云存储平台
Lepton AI 是一款面向开发者的 AI 平台,旨在提供易用.高效且可扩展的基础设施能力.该平台适用于各种训练.推理需求,GPU充足,在保证高性能的同时,能够灵活应对不断变化的工作负载.用户可以快 ...
- wget命令简单使用
wget是Linux下一个文件下载工具.wget支持HTTP.HTTPS.FTP协议,可使用HTTP代理. 所谓自动下载,是指 wget 可以在用户退出系统的之后在继续后台执行,直到下载任务完成. w ...
- mysql 使用 ibd 恢复数据
分四步: 1. 按照ibd对应的表结构,创建新表: 2. 执行: ALTER TABLE `t_健忘就多写博客` DISCARD TABLESPACE; 或者 停止mysql服务后,删除对应的 xxx ...
- mysl 修改数据存储位置后服务启动后停止
在 Windows 系统中安装完 mysql 后,如果是生产用的机器,通常会修改数据存储位置.基本步骤: 1. 停止 mysql 服务: 2. 修改 my.ini 文件中的 datadir=" ...
- dart变量类型详解
1==> 三个单引号的作用 String Str = ''' qijqowjdo 哈哈嘿嘿黑 '''; print(Str); 这样使用三个单引号,输出来换行:方便我们观看而已哈 2==> ...
- Mac安装Prometheus + Grafana
一.安装Prometheus 1.下载安装 brew install prometheus 2.安装路径 /opt/homebrew/Cellar/prometheus/3.1.0 3.修改配置文件 ...
- docker-镜像的作用
ls /var/lib/docker tree /var/lib/docker overlay2 docker pull ubuntu:8.0 docker images ls /var/lib/do ...
- C# 获取计算机唯一标识
C# 获取计算机唯一标识 原文链接 private static string _sFingerPrint { get; set; } /// <summary> /// 计算机唯一标识 ...
- 并发编程 - 线程同步(九)之信号量Semaphore
前面对自旋锁SpinLock进行了详细学习,今天我们将学习另一个种同步机制--信号量Semaphore. 01.信号量是什么? 在 C# 中,信号量(Semaphore)是一种用于线程同步的机制,能够 ...