Java 在单元测试中Lombok实例化之前加载Spring启动组件
我开发了一种包装器,使其能够作为自定义记录器工作。我正在使用Java 在单元测试中Lombok实例化之前加载Spring启动组件,java,spring,spring-boot,junit4,lombok,Java,Spring,Spring Boot,Junit4,Lombok,我开发了一种包装器,使其能够作为自定义记录器工作。我正在使用@CustomLogLombok注释实例化这个类,只是为了使它更简单、更干净。接下来是一件棘手的事情:这个包装器背后的想法是使用一个通用的记录器(如org.slf4j.logger)和一个自定义的监控类,每次我调用log.error(),正确的消息都会被记录在终端中,事件会被发送到我的监控工具(本例中是普罗米修斯) 为了实现这一点,我上了以下课程: CustomLoggerFactoryLombok调用的工厂,用于实例化我的自定义记录器
@CustomLog
Lombok注释实例化这个类,只是为了使它更简单、更干净。接下来是一件棘手的事情:这个包装器背后的想法是使用一个通用的记录器(如org.slf4j.logger
)和一个自定义的监控类,每次我调用log.error()
,正确的消息都会被记录在终端中,事件会被发送到我的监控工具(本例中是普罗米修斯)
为了实现这一点,我上了以下课程:
CustomLoggerFactory
Lombok调用的工厂,用于实例化我的自定义记录器公共最终类CustomLoggerFactory{
公共静态CustomLogger getLogger(字符串类名称){
返回新的CustomLogger(类名);
}
}
CustomLogger
将收到类名,然后调用org.slf4j.LoggerFactory
公共类自定义记录器{
私有org.slf4j.Logger;
私人PrometheusMonitor PrometheusMonitor;
私有字符串类名;
公共CustomLogger(字符串类名称){
this.logger=org.slf4j.LoggerFactory.getLogger(类名);
this.className=className;
this.monitor=SpringContext.getBean(PrometheusMonitor.class);
}
}
PrometheusMonitor
类是负责创建度量标准之类的东西的类。这里最重要的是,它由Spring Boot管理@组件
公共类PrometheusMonitor{
私人计量登记;
公共PrometheusMonitor(计量登记计量登记){
this.meterRegistry=meterRegistry;
}
}
CustomLogger
访问PrometheusMonitor
,我需要一个额外的类,以便从非Spring管理的类获取Bean/访问上下文。这是SpringContext
类,它有一个static
方法通过提供的类获取bean@组件
公共类SpringContext实现ApplicationContextAware{
私有静态应用上下文上下文;
公共静态T getBean(类beanClass){
返回context.getBean(beanClass);
}
@凌驾
public void setApplicationContext(ApplicationContext上下文)引发BeansException{
SpringContext.context=context;
}
}
因此,在运行应用程序时,所有这些都可以正常工作。我确保先加载SpringContext
类,所以一旦每个CustomLogger
被实例化,它就可以工作了
但是这里出现了一个大问题:在对我的应用程序进行单元测试时,这不起作用。我尝试了很多方法,发现了一些可能对我有帮助但我正在努力避免的解决方案(例如使用PowerMockito)。Lombok正在处理我添加到测试类中的任何@before
方法之前的@CustomLog
注释。调用getBean()
方法后,我会得到一个异常原因context
为null
我的猜测是,如果我能在Lombok变魔术之前强制加载
SpringContext
,我就可以解决这个问题,但我甚至不确定这是否可能。非常感谢您花时间阅读此文章。我能提供的更多信息,请告诉我。注意:像平常一样登录到slf4j,并在slf4j框架中注册一个额外的处理程序,这样slf4j将向您转发任何日志(除了其他处理程序之外,例如生成日志文件的处理程序),似乎可以更好地满足您的自定义日志记录需求
Lombok正在处理@CustomLog
生成的日志字段是静态的。如果注释有任何帮助,您需要在类之前使用
@BeforeClass
,但这可能也不及时。龙目山的魔法在这里似乎不相关。看看delombok告诉你lombok在做什么:它只是。。一个静态字段,在声明时初始化。我设法解决了这个问题,稍微改变了CustomLogger
的工作方式。这意味着,您可以在第一次使用它时使用它,而不是将monitor
字段与记录器一起实例化。例如:
公共类自定义记录器{
私有org.slf4j.Logger;
私人监听;
公共CustomLogger(字符串类名称){
this.logger=org.slf4j.LoggerFactory.getLogger(类名);
}
公共无效信息(字符串消息){
this.logger.info(消息);
}
公共无效错误(字符串消息){
此.logger.error(消息);
if(this.monitor==null){
this.monitor=SpringContext.getBean(PrometheusMonitor.class);
}
此.monitor.send(消息);
}
}
但毕竟,我决定不采用这种方法,因为我认为这不是最好的方法,也不值得这样做。起初我是这样想的(处理其他框架发送的日志事件)但是对于我现在拥有的日志,我使用了一些自定义参数,如
enum
s,这些参数不能与Slf4j日志调用一起发送。所以我看不到一种处理方法可以满足我的需要。