[英]Spring @Autowired field is null inside an overrided method
我有一个实现 MessageListener 的类,用于 Spring Data Redis。 它适用于 Redis,但我有一个奇怪的行为。 我有一个 test() 方法来测试 messageService 实例是否为空。 它需要调用 Jpa Repository 在 MySql DB 中进行持久化。 奇怪的行为是,如果在 getNewMessage() 和 printWelcome() 方法中调用它,则它不为 null(然后我可以使用 CRUD 方法进行持久化),但它在由组织覆盖的 onMessage() 方法中为null .springframework.data.redis.connection.MessageListener 类。这是我的控制器类:
@Controller
public class StatoController implements MessageListener{
@Autowired
private MessageService messageService;
public static final List<DeferredResult<Message>> messageDeferredResultList = new ArrayList<>();
@RequestMapping(value = "sec/redis", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public DeferredResult<Message> getNewMessage() throws Exception {
Long deferredResultTimeout = 0L;
final DeferredResult<Message> deferredResult = new DeferredResult<>(deferredResultTimeout);
deferredResult.onCompletion(() -> {
messageDeferredResultList.remove(deferredResult);
});
deferredResult.onTimeout(() -> {
messageDeferredResultList.remove(deferredResult);
});
messageDeferredResultList.add(deferredResult);
try{
//not null
List<Message> list=messageService.findAll();
}
catch(Exception ex){ex.printStackTrace();}
return deferredResult;
}
@RequestMapping(value = {"sec/stato.html"}, method = RequestMethod.GET)
public ModelAndView printWelcome(ModelMap model) {
try{
//not null
List<Message> list=messageService.findAll();
}
catch(Exception ex){ex.printStackTrace();}
ModelAndView mav = new ModelAndView("secured/stato");
return mav;
}
@Override
public void onMessage(Message msg, byte[] bytes) {
try{
//NullPointerException
List<Message> list=messageService.findAll();
}
catch(Exception ex){ex.printStackTrace();}
// set the deferred results for the user
messageDeferredResultList.stream().forEach((deferredResult) -> {
deferredResult.setResult(msg);
});
}
这是消息到达并调用 onMessage 方法时的堆栈跟踪:
java.lang.NullPointerException at infn.lns.acceleratori.controller.StatoController.onMessage(StatoController.java:95) at org.springframework.data.redis.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:299) at org. springframework.data.redis.listener.RedisMessageListenerContainer.executeListener(RedisMessageListenerContainer.java:245) at org.springframework.data.redis.listener.RedisMessageListenerContainer.processMessage(RedisMessageListenerContainer.java:235) at org.springframework.data.redis.listener。 RedisMessageListenerContainer$1.run(RedisMessageListenerContainer.java:960) 在 java.lang.Thread.run(Thread.java:745)
当有来自 Redis 的消息时调用 onMessage() 方法。 我在我的 context-config.xml 中正确地添加了这个:
<context:annotation-config/>
<context:component-scan base-package="org.springframework.data.redis, infn.lns.acceleratori"/>
这是包含数据 redis 的 bean 声明的配置类:
@Configuration
public class AppConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
RedisTemplate< String, Object > redisTemplate() {
final RedisTemplate< String, Object > template = new RedisTemplate< >();
template.setConnectionFactory( jedisConnectionFactory() );
template.setKeySerializer( new StringRedisSerializer() );
template.setHashValueSerializer( new GenericToStringSerializer< >( Object.class ) );
template.setValueSerializer( new GenericToStringSerializer< >( Object.class ) );
return template;
}
@Bean
MessageListenerAdapter messageListener() {
return new MessageListenerAdapter( new RedisMessageListener() );
}
@Bean
RedisMessageListenerContainer redisContainer() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory( jedisConnectionFactory() );
container.addMessageListener( messageListener(), new ChannelTopic( "queue" ) );
return container;
}
}
这是创建为 Bean 的 MessageServiceImpl:
@Service
public class MessageServiceImpl implements MessageService {
@Resource
private MessageRepository messageRepository;
@Override
@Transactional
public Message create(Message event) {
Message createdMessage = event;
return messageRepository.save(createdMessage);
}
我想知道为什么 messageRepository 的实例在 getNewMessage() 和 printWelcome() 方法中正确自动装配,而不是在覆盖的 onMessage() 方法中。
编辑:
现在我将我的监听器和控制器分成两个不同的类。 我有这个新课程:
public class RedisMessageListener implements MessageListener {
@Autowired
private MessageService messageService;
@Override
public void onMessage(Message message, byte[] paramArrayOfByte) {
System.out.println(messageService==null);
messageDeferredResultList.stream().forEach((deferredResult) -> {
deferredResult.setResult(message);
});
}
}
但 messageService 始终为空。 它只是一颗豆子!
好的,感谢@dunni,我找到了解决方案。 我还在自己创建 RedisMessageListener 的实例。 允许 Spring 创建它(通过添加 @Component 注释)并将它注入到我创建 MessageListenerAdapter 的方法中,使用 @Autowired,我解决了这个问题。
@Vipul
这意味着您的 MessageListenerAdapter 配置自己而不是 spring 创建了一个 TaskEventSubscriber bean。
错误:
@Bean
MessageListenerAdapter taskEventListener() {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new TaskEventSubscriber());
return messageListenerAdapter;
}
正确:
@Autowired
private TaskEventSubscriber taskEventSubscriber;
@Bean
MessageListenerAdapter taskEventListener() {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(taskEventSubscriber);
RedisSerializer stringSerializer = new StringRedisSerializer();
messageListenerAdapter.setSerializer(stringSerializer);
return messageListenerAdapter;
}
(对不起,我不能评论)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.