1
@Service
public class LogProcessorServiceImpl {
    @Autowired
    private static ApplicationConfigurationService applicationConfigurationService;

    public static void processPageRequestsLogs() {
        if(applicationConfigurationService==null) {
            System.out.println("autowire failed");
        }

我有 ApplicationConfigurationService 服务像这样在整个地方自动连接,它工作正常。正在扫描此类的包,所以这不是问题。它可能与调用此特定方法的方式有关。我有一个在所有其他 servlet 之后加载的 servlet,它会触发一个计时器,该计时器以 60 秒的延迟执行上述方法。我认为应该完成所有自动装配。

public class ProcessSchedulerServlet implements javax.servlet.Servlet {
    Timer timer=new Timer();

     @Override
     public void init(ServletConfig arg0) throws ServletException {
         timer.scheduleAtFixedRate(new TimerTask() {
             public void run() {
                 LogProcessorServiceImpl.processPageRequestsLogs();
             }
         }, 60*1000, 120*1000);
     }

这是我真正使用 ApplicationConfigurationService 后会发生的情况:

autowire failed
Exception in thread "Timer-1" java.lang.NullPointerException
at com.siteadmin.services.impl.LogProcessorServiceImpl.processPageRequestsLogs(LogProcessorServiceImpl.java:39)
at com.siteadmin.servlets.ProcessSchedulerServlet$1.run(ProcessSchedulerServlet.java:20)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

=== 2012-11-18 ========================================== ===================

另请参阅:如何进行 Spring 自动装配?

4

1 回答 1

3

您不能在 Spring 中自动装配静态字段,这在此处进行了讨论

作为替代方案,如果您LogProcessorService驻留在根 Web 应用程序上下文中,则可以使用 Spring WebApplicationContextUtils实用程序类自动装配它。

public class ProcessSchedulerServlet implements javax.servlet.Servlet {
     Timer timer=new Timer();

     @Autowired
     LogProcessorService logProcessorService;

     @Override
     public void init(ServletConfig arg0) throws ServletException {
         WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext())
            .getAutowireCapableBeanFactory().autowireBean(this);

         final LogProcessorService svc = this.logProcessorService;
         timer.scheduleAtFixedRate(new TimerTask() {
         public void run() {
             svc.processPageRequestsLogs();
         }
         }, 60*1000, 120*1000);

通常,您应该避免使用 Java 单例,因为使用 Spring 单例就足够了。

此外,如果您LogProcessorServiceImpl使用@Service注释声明,则意味着它是 Spring 单例,因此您根本不应该在那里使用静态字段。

PS这个答案是关于自动装配的,它假设TimerTask的想法是正确的,在真正的应用程序中考虑使用Spring Scheduling API

于 2012-11-18T05:39:42.033 回答