Spring Boot - 如何使用非默认构造函数@Autowired Bean?

时间:2016-11-04 14:01:12

标签: spring spring-boot

我发现很多关于使用非空构造函数here使用@Autowired的信息。但我甚至无法解决当前的问题。

我有一个用于记录的界面。我记录了数据库中的每个条目。出于这个原因,我必须知道类名,哪个类使用记录器。

我的第一个想法:创建一个Logger的新实现,它有一个非空的构造函数。因此,在创建此记录器的新实例时,您必须设置名称。

我的界面如下所示:

public interface Logger{
  public void log(String name, String msg);
}

其实现如下:

@Service
public class LoggerImpl implements Logger{
 private String className;

 LoggerImpl(String className){ this.className = className }

 @Override
 public void log(String name, String msg) { // print and save in the database }
}

我的应用程序的每个地方都想使用这个记录器 - 接口。例如,在某些商业类中,我以这种方式使用Logger:

@Service
public class ServiceName {
 private Logger logger;

 @Autowired
 public ServiceName(){
   logger = new LoggerImpl("ServiceName");
 }

 public void someMethod(){
    logger.log("name", "this is a log!");
 }
}

但我的应用程序告诉我,他没有数据库通信并抛出NullPointerException,同时将日志保存在数据库中。在创建非空构造函数之前,此通信有效。所以我的猜测是,当我手动创建此LoggerImpl时,此对象不再位于spring应用程序上下文中。有什么想法要解决?谢谢。 编辑:我正在使用Spring Boot,但我没有任何XML文件。

2 个答案:

答案 0 :(得分:5)

您可能需要查看新的InjectionPoint

@Configuration
public class LoggerConfig {

  @Bean
  @Scope("prototype")
  public Logger logger(InjectionPoint injectionPoint) {
    //this is the class where the logger will be used     
    Class<?> theClassYouAreLookingFor = injectionPoint.getMember().getDeclaringClass();
    return findOrCreateYourLogger(theClassYouAreLookingFor);
  }
}

使用Logger只需像通常用其他Bean一样注入它。

答案 1 :(得分:4)

我认为在这种情况下用@Service注释是不够的。 Spring将无法创建LoggerImpl实例。

你必须告诉Spring如何创建实例。 使用XML配置时,您应该

<bean id="loggerForX" class="LoggerImpl ">
  <constructor-arg index="0" value="X" />
</bean>

使用javaconfig时

@Configuration
public class LoggerConfiguration {

  @Bean
  public Logger loggerForX() {
    return new LoggerImpl("X");
  }

}

然后你就可以将@Autowire Logger作为

@Autowire  Logger loggerForX;

如果这不起作用,请尝试自动装配loggerForX变量ab

@Autowire @Qualifier("loggerForX") Logger loggerForX;

使用这种方法,您必须为每个想要记录器的类创建单独的bean。将LoggerFactory创建为bean并注入LoggerFactory可能更好。 LoggerFactory必须有方法来创建Logger

@Service
class LoggerFactory  {

  public Logger loggerFor(String name) {
    return new LoggerImpl(name);
    }

}

LoggerFactory有默认构造函数,可以随时随地@Autowired