【问题标题】:Spring autowired bean causes null pointerSpring自动装配bean导致空指针
【发布时间】:2014-11-17 10:18:02
【问题描述】:

我有一个使用服务的记录器类。每次创建新的记录器时,我都希望能够访问单例范围的记录服务。

我将日志服务自动连接到记录器中,但是返回了一个空指针异常。我尝试了一些解决方案:

  1. 在应用程序上下文中手动定义 bean,
  2. 试图让记录器由 spring 管理,但这只会导致更多问题。

我试图让它在我的 junit 测试中工作,并且我确实指定了上下文文件以使用不同的应用程序上下文。但是,即使保持相同也不能解决问题。

请在下面找到代码:

以下是应用程序上下文的摘录。

<context:component-scan base-package="com.platform"/>
<bean id="asyncLoggingService" class="com.platform.services.AsyncLoggingServiceImplementation" scope="prototype"/>

以下是Logger类。

package com.platform.utils;


import com.platform.services.AsyncLoggingService;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class OurLogger
{

  private static Logger logger;

  @Autowired
  private AsyncLoggingervice asyncLoggingService;

  public OurLogger(Class Clazz)
  {
    logger = LoggerFactory.getLogger(Clazz);
  }


  public void trace(TraceableObject object, String message)
  { 
    //Do nothing yet
  }

}

然后我在另一个服务中使用 Logger 来记录正在发生的事情。 (我写另一个记录器的原因是使用 RabbitMQ 服务器)在服务中,我实例化了一个新的记录器实例,然后相应地使用它。

@Service
public class AsyncAccountServiceImplementation implements AsyncAccountService
{
  private static final String GATEWAY_IP_BLOCK = "1";

  private static OurLogger logger = new      OurLogger(AsyncAccountServiceImplementation.class);

...
}

当我尝试调用asyncLoggingService 上的任何方法时,OurLogger 中出现空指针。

然后我尝试使用 JUnit 测试 AsyncAccountService。我确保我添加了不同的应用程序上下文,但它似乎仍然导致空指针异常。

如果您需要更多信息,请告诉我。我已经看到了解决此问题的方法,但它们似乎不起作用,所以也许我在某个地方犯了一个错误,或者我没有完全正确地理解这一切。

【问题讨论】:

  • Spring 应该如何自动装配它不知道的实例。您正在自己创建新实例,而您应该使用由 spring 管理的实例。
  • 据我所知(如果我可能错了,请纠正我)bean 是在应用程序上下文中指定的,然后在 OurLogger 实例中使用(同名)。我看到的唯一灰色区域是创建新的 OurLogger 实例,但肯定可以在这样的对象实例中使用自动装配服务。感谢您迄今为止的评论。
  • 不,它不是...这仅适用于 spring 定义和托管的 bean。只要您执行new OurLogger,就不会发生任何事情。除非您将 AspectJ 与 @Configurable 结合使用。
  • 但是出于好奇,为什么不简单地为您的日志框架创建一个附加程序呢?这样你就可以在你的代码中简单地使用 SLF4J 并拥有一个基于 RabbitMQ 的附加程序(Logback 或 Log4j)来进行实际的日志记录。
  • 它将大大简化您的工作。 Spring AMQP 提供了一个 implementation for Log4j(我刚刚注册了 an issue 一个 Logback :))。

标签: java spring junit autowired spring-annotations


【解决方案1】:

当你通过 new 创建对象时,autowire\inject 不起作用...

请参阅此link 和此link 了解一些解决方法。

无论如何,如果您要注入记录器,我建议您 this 我对另一个主题的回答。

【讨论】:

  • 谢谢,我相信你的工作会奏效,但据我所知,以这种方式直接从上下文中获取 bean 被认为是不好的做法。 stackoverflow.com/questions/812415/…
  • 这不是一个真正的坏习惯,只是解决问题的不同方法:) 但同一事物的不同方面:) 无论如何,您是否按照我的建议考虑过注入记录器?
【解决方案2】:

如果你使用 AspectJ,你可以使用@Configurable:

@Configurable
public class OurLogger {
  ..
}

见:Using AspectJ to dependency inject domain objects with Spring

【讨论】:

  • 感谢您的帮助,正如 M. Deinum 建议的那样。我将对此进行研究,因为它看起来很有希望(而且很有趣)
【解决方案3】:

在您的应用程序上下文中,您必须参考您的 Logger:

<context:component-scan base-package="com.platform"/>
<bean id="asyncLoggingService" class="com.platform.services.AsyncLoggingServiceImplementation" scope="prototype"/>
<bean id="ourLogger" class="com.platform.utils.OurLogger"/>

然后你必须将它注入你的服务:

@Service
public class AsyncAccountServiceImplementation implements AsyncAccountService
{

 private static final String GATEWAY_IP_BLOCK = "1";

 @Autowired
 private OurLogger logger;

}

【讨论】:

  • 这将是我的方法,但是我希望记录器使用类名实例化 slf4j 记录器。所以我认为@Configrable 方式应该允许我遵循与您在此处描述的大致相同的方法。
【解决方案4】:

使用 spring 框架单元测试而不是 JUnit 测试来注入你的 spring bean。

可能会对你有所帮助。

【讨论】:

    【解决方案5】:

    只想加我的 2 美分。

    当我不太习惯the life in the IoC world 时,我曾经遇到过同样的问题。我的一个 bean 的 @Autowired 字段在运行时为空。

    根本原因是,我不是使用由 Spring IoC 容器维护的自动创建的 bean(其 @Autowired 字段是 indeed 正确注入),而是 newing 我自己的该 bean 实例并使用它.当然这个@Autowired字段是null,因为Spring没有机会注入它。

    【讨论】:

    • 我认为如果你创建一个新的类的最终实例,这是解决这类问题的最佳方案。
    猜你喜欢
    • 2015-11-16
    • 2017-11-20
    • 2014-10-07
    • 2012-10-02
    • 2017-10-22
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2014-09-08
    相关资源
    最近更新 更多