我发现很多关于使用非空构造函数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文件。
答案 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
。