SpringBoot在某些框架 如netty的handler类中注入依赖报null异常
spring在使用一些安全或者通信框架,如netty,t-io,spring-security时,总会遇到一些handler处理类,而在这些类中往往无法直接使用@Autowired注解实现依赖注入,调用的时候直接报null异常。这是spring容器的初始化顺序造成的。解决方法如下:
1、使用工具类直接获取bean
这个方案非常简单,直接新建一个工具类,然后在需要的位置调用get方法获取想要的bean即可。
package com.example.demo.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
2、使用@PostConstruct注解
使用@PostConstruct注解一个init方法来完成初始化,该方法会在bean注入完成后被自动调用,执行顺序为:构造函数 >> @Autowired >> @PostConstruct。
当前是一个抽象类,在其中使用@Autowired注入了消息中间件的相关依赖,然后使用@PostConstruct注解init方法实现后置处理器。
public abstract class AbsCommonBsHandler implements AbsCommonBsHandlerIntf {
protected static AbsCommonBsHandler absCommonBsHandler;
@Autowired
public JmsMessagingTemplate messagingTemplate;
@Autowired
public Queue queue;
@Autowired
public Topic topic;
@PostConstruct
public void init() {
absCommonBsHandler = this;
}
// 此处省略255个字符
................................
}
当前使用子类继承上面的AbsCommonBsHandler抽象类,并用@Component注解注册为组件。
关键语句:
absCommonBsHandler.messagingTemplate.convertAndSend(absCommonBsHandler.queue, msg);
@Component
public class JJTSTReqHandler extends AbsCommonBsHandler {
/**
* 处理消息
*/
@Override
public void handler(SPPacket packet, String bsBody, ChannelContext channelContext) throws Exception {
// 此处省略很多字符
................................
// 将接收到的消息送入队列
absCommonBsHandler.messagingTemplate.convertAndSend(absCommonBsHandler.queue, msg);
}
}
这样就能在handler中正常调用注入的bean了。正常操作不需要抽象类,恰好项目中有这一段,所以直接copy了。