0

我正在编写一个自定义评估器,我想在其中自动装配另一个 bean。我无法这样做,因为评估器由记录器初始化,而 bean 由弹簧上下文初始化。以下是我的代码示例:

在 logback-spring.xml 中:

 <appender name="myAppender" class="ch.qos.logback.classic.net.SMTPAppender">
           <evaluator class="com.package.CustomEvaluator">
            <marker>FATAL</marker>
            <interval>1000000</interval>
           </evaluator>
 </appender>

我的自定义评估器:

@Slf4j
@Component
public class CustomEvaluator extends OnMarkerEvaluator {
    @Autowired
    private MyService myService;

    @Override
    public boolean evaluate(ILoggingEvent event) throws EvaluationException {
        \\logic goes here
    }
}

我将 MyService 的对象始终设为 null(这是预期的)。有什么解决方法吗?

4

1 回答 1

0

它认为这是不可能的,因为作为内部 logback 抽象的 Evaluator 不是由 spring 管理/初始化的,所以很明显 spring 不能将任何东西自动连接到 evaluator 中。

另外请注意,即使在应用程序上下文启动之前,该 logback 也会被初始化。

当然,您可以为应用程序上下文提供一些全局持有者类,并在 main 方法中为其设置上下文,然后在此评估器中获取对它的引用,如下所示:

public class ApplicationContextHolder {
        private static ApplicationContext context;
        // call it in main() method 
        public static void setContext(ApplicationContext ctx) {context = ctx;}
        public static ApplicationContext getContext() {return context;} 
}

class CustomEvaluator extends OnMarkerEvaluator {
    public boolean evaluate(ILoggingEvent event) throws EvaluationException {
        ApplicationContext ctx = ApplicationContextHolder.getContext();
        if(ctx == null) {return false;} // not yet initialized / accessible
        MyService myService = ctx.getBean(MyService.class);
    }
}

但总而言之,我相信这是一个非常丑陋的解决方案。

作为一个建议,我认为您应该考虑重构逻辑,以便在应用程序中决定是否根据日志记录事件发送电子邮件(我假设,这是由 spring boot 驱动的,因此您可以访问MyService)

鉴于当前的实现:

  public foo() {
     LOGGER.info("This should be sent by email");
  }

我建议应用程序的一部分:

  @Component
  public class MyLogic {
      @Autowired MyService myService;

      public void foo() {
          if(myService.shouldSend()) {
             LOGGER.info("This should be sent by email");
          }
      }
  }
于 2019-08-08T05:40:03.007 回答