背景
本人是接触springBoot的小白,最近做了一个通过SockJs和SimpMessagingTemplate.convertAndSend()推送前端。一开始对Spring不了解,一路都是通过main函数引用。SimpMessagingTemplate在MsgHandler类中,我在main函数中一路调用函数,
public static void main(String[] args)
{
MsgHandler msgHandler =new MsgHandler();
msgHandler.start();
}
在MsgHandler类中的构造函数中使用SimpMessagingTemplate.convertAndSend()推送前端。
@Component
public class MsgHandler {
@Autowired
SimpMessagingTemplate template;
public MsgHandler( ) {
}
@Override
protected void doStart() {
template.convertAndSend("/topic/subscribe/" , "hello");
}
根据以上的代码运行,当程序调用到MsgHandler( ) 时, template.convertAndSend("/topic/subscribe/" , “hello”);直接会被跳过,提示error。然后慢慢调试发现template时null,没有被注入。当我把 template.convertAndSend("/topic/subscribe/" , “hello”);写入main函数,就调用成功。上网查找了很久了才找到了原因。
现象
当使用SpringBoot注入 SimpMessagingTemplate,并用main函数和构造一直调用 template.convertAndSend( );时出现错误,跳过了convertAndSend方法。发送前端失败。
原因
在使用springBoot框架注入时,加入@Component注解的类,spring在启动SpringApplication.run()时才会加载@Component注解的类,当扫描@Component注解的类时,spring不用在main函数调用就会示例化,并加载构造函数还会执行@Autowired注入。但是如果在main函数中调用了类的实现,那么这些调用的类要比@Component注解类和@Autowired注入执行的快。所以在本例中,执行 template.convertAndSend("/topic/subscribe/" , “hello”);是通过main函数一路调用进行的。还没有等待MsgHandler类被扫描和 SimpMessagingTemplate注入就已经执行了convertAndSend,所以会报error。
解决办法
将main函数的调用去掉,使用@Component注解来扫描类,自动加载到spring中。对MsgHandler的start方法可以使用 @PostConstruct注解star方法。
PostConstruct注解时spring加载后被注解的类执行一次的方法。这样就可以等所有的@Component和@Autowored住入后再执行template.convertAndSend( );
总结
在使用SpringBoot 框架时一定要注意main函数调用与@Autowried注入的顺序。
main函数调用方法>@Component类的@Autowored注入。
小白献丑了。