当想在收到客户端消息时执行查库操作,发现使用@Autowired方式注入的service为null。其原因是websocket每次都会产生新的对象,与spring的单例模式冲突。
解决办法:
添加一个容器类实现ApplicationContextAware
@Component
public class SpringContext implements ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(SpringContext.class);
private static ApplicationContext applicationContext;
private static DefaultListableBeanFactory beanFactory;
public static <T> T getBean(String name, Class<T> clazz) {
return applicationContext.getBean(name, clazz);
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static DefaultListableBeanFactory getBeanFactory() {
return beanFactory;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContext.applicationContext = applicationContext;
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext ;
beanFactory = (DefaultListableBeanFactory) configurableApplicationContext
.getBeanFactory();
}
public static void printBeanDefinitionNames() {
String[] beanDefinitionNames = applicationContext
.getBeanDefinitionNames();
for (int i = 0; i < beanDefinitionNames.length; i++) {
logger.info(beanDefinitionNames[i]);
}
}
public static XmlBeanDefinitionReader getXmlBeanDefinitionReader() {
return new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
}
/**
* 动态加载bean
* @param fileName
* @throws BeanDefinitionStoreException
* @throws IOException
*/
public static void loadBean(String fileName)
throws BeanDefinitionStoreException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = getXmlBeanDefinitionReader();
beanDefinitionReader.setResourceLoader(applicationContext);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(
applicationContext));
beanDefinitionReader.loadBeanDefinitions(applicationContext
.getResources(fileName));
}
public static void loadBean(String fileName, String propertyHolderBeanName)
throws BeanDefinitionStoreException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = getXmlBeanDefinitionReader();
beanDefinitionReader.setResourceLoader(applicationContext);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(
applicationContext));
beanDefinitionReader.loadBeanDefinitions(applicationContext
.getResources(fileName));
if (propertyHolderBeanName != null) {
postProcessBeanFactory(propertyHolderBeanName);
}
}
public static void postProcessBeanFactory(String propertyHolderBeanName)
throws BeanDefinitionStoreException, IOException {
BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor) SpringContext
.getBean(propertyHolderBeanName);
bfpp.postProcessBeanFactory(SpringContext.getBeanFactory());
}
}
再在@ServerEndpoint注解的类中添加用到的service
MessageService messageService = (MessageService) SpringContext.getBean("messageServiceImpl");
这样就能够实现所达到的效果。
但是到这里我运行代码仍然报空指针错误,发现applicationContext并没有初始化(其实是在调用getBean后面才初始化)。在@ServerEndpoint下添加@Lazy注解,问题解决。