当前位置: 首页 > 知识库问答 >
问题:

Spring@Autowired字段在重写方法内为null

齐文栋
2023-03-14

我有一个实现MessageListener的类,用于Spring Data Redis。它在Redis上运行良好,但我有一个奇怪的行为。我有一个test()方法来测试MessageService实例是否为空。它需要调用Jpa Repository以获取MySql DB中的持久性。奇怪的行为是,如果在getNewMessage()和printWelcome()方法中调用它,它就不会为空(然后我可以使用CRUD方法来实现持久性),但在org.springframework.data.redis.connection.MessageListener类覆盖的onMessage()方法中它为空。这是我的Controller类:

@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)atorg.springframework.data.redis.listener.RedisMessageListenerContainer.processMessage(RedisMessageListenerContainer.java:235)位于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始终为空。它只是一粒豆子!

共有2个答案

乜明朗
2023-03-14

@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;
    }

(抱歉我不能评论)

夏英发
2023-03-14

好的,多亏了@dunni,我找到了解决方案。我还在自己创建RedisMessageListener的实例。允许Spring创建它(通过添加@Component注释)并将其注入到我使用@Autowired创建MessageListeneraAdapter的方法中,我解决了这个问题。

 类似资料:
  • 问题内容: 我有一个具有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示该bean和该bean都在创建,但是每当我尝试在服务bean上调用该方法时,都会得到一个a 。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 本文向大家介绍为什么我的Spring @Autowired字段为空?

  • 我正在学习Spring,据我所知,当我们对一个具有泛型名称(而不是setter方法)的方法使用@Annotation时,该方法的参数是自动连线的。

  • 我有混合堆栈:EJB和Spring。为了将Spring自动连接到EJB,我使用(不确定这是否会影响我遇到的问题)。 Whlie试图通过以下方式自动连接bean: 我得到错误: 据我所知,问题是使用了JDK代理(因为实现了接口),而我需要cglib代理。 不确定是否相关,但我运行的是glassfish 3.1.x。 和stacktrace(部分,因为我不能在这里公开所有类名:

  • 我使用的是Spring3.1.4.Release和Mockito1.9.5。在我的春季课上,我有: 我想为我的“Defaulturl”字段模拟一个值。请注意,我不想模拟其他字段的值--我希望保持这些字段的原样,只保留“Defaulturl”字段。还要注意,我的类中没有显式的“setter”方法(例如),我不想仅仅为了测试的目的创建任何方法。 既然如此,我如何模拟一个字段的值呢?

  • 本文向大家介绍为什么在重写 equals方法的同时必须重写 hashcode方法,包括了为什么在重写 equals方法的同时必须重写 hashcode方法的使用技巧和注意事项,需要的朋友参考一下 我们都知道Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类。 其 equals 方法比较的是两个对象的引用指向的地址,hashcode 是一个本地方法,返回的是对象地址值。O

  • 我有一个带有JSF2 end Spring4.3的webmodule。在backing bean中,我使用对jar的服务进行DI。在EAR模块中有WAR、带有Spring的JAR和带有Spring配置文件的JAR。 下面是片段: : 当我在Backing Bean中使用时,值为(没有任何异常)。我的JSF bean 你能帮帮我吗,拜托。