ThreadPoolTask​​Executor 中的@Autowired 不起作用

@Autowired in ThreadPoolTaskExecutor doesn't work

我试图 运行 在 Java GUI 应用程序中按下按钮时的异步线程。

我的代码是:

配置class:

@Configuration
@ComponentScan({"khartn", "khartn.torrentsuploader.processor"})
public class AppConfig {

    @Bean(initMethod = "init")
    public NewJFrame mainForm() {
        System.out.println("init mainForm");
        return new NewJFrame();
    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(5);
        pool.setMaxPoolSize(10);
        pool.setWaitForTasksToCompleteOnShutdown(true);
        pool.initialize();
        return pool;
    }

}

JFrame class:

public class NewJFrame extends javax.swing.JFrame {

    @Autowired
    FileProcessor fileProcessor;
    @Autowired
    ThreadPoolTaskExecutor taskExecutor;

   private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        taskExecutor.execute(new Runnable() {

            @Autowired
            MyDirectoryReader myDirectoryReader;

            @Autowired
            AuthThread authThread;

            @Override
            public void run() {
                jLabel3.setText("Авторизация...");
                Boolean authSuccessfull = false;
                while (!authSuccessfull) {
                    authSuccessfull = authThread.auth();

                }
                jLabel3.setText("Загрузка файлов");

                myDirectoryReader.readDir();
            }

        });

    }   

我在线上遇到错误

authSuccessfull = authThread.auth();



java.lang.NullPointerException
    at khartn.torrentsuploader.form.NewJFrame.run(NewJFrame.java:162)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

为什么会出现这个异常?

以及如何解决这个异常?

为什么我的组件没有自动装配?

谢谢。

如果您的 class 不是由上下文启动的,Bean 将不会自动装配。也就是说,

如果您的 class NewJFrame 是由 new 关键字手动启动的,spring 框架将无法 autowire 属性 里面的变量 class.

做这样的事情。

@Component("mainForm")
public class NewJFrame extends javax.swing.JFrame {

并从配置 java 文件中删除 bean 方法 mainForm。然后重新设计 NewJform 如下。我没有编译这个程序。因此,请原谅任何编译错误。

注意:关键是确保 class 中的所有 @Autowired 属性由 DINOT 启动由 new。您的 Runnable 也由 new 关键字启动,这就是为什么我们需要从匿名 Runnable 对象中取出 myDirectoryReaderauthThread

@Component("mainForm")
public class NewJFrame extends javax.swing.JFrame {

    @Autowired
    FileProcessor fileProcessor;

    @Autowired
    ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    MyDirectoryReader myDirectoryReader;

    @Autowired
    AuthThread authThread;


    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        taskExecutor.execute(new Runnable() {

           @Override
           public void run() {
              ...
              authSuccessfull = authThread.auth();
              ...
           }
    });
}   

基本上,你不应该使用

taskExecutor.execute(new Runnable(){
    // do something here
});

首先你要明白什么是Managed Bean和Unmanaged Bean。当您使用 Spring 时,您的 java classes 的所有实例都将被实例化,并且 "pre-loaded" 在您启动应用程序的那一刻。换句话说,所有 classes 都将由 spring 容器实例化和管理。在实践中,您使用@Component(或@Bean,如果在@Configuration class 完成)和@Autowired 注释。

当您为 class Runnable 使用 "new" 关键字时,您正在做的是打破让 spring 管理所有 bean 的规则(或 classes)。现在 "new Runnable(){}" 不再由 spring 管理,但您期望 spring 将所有 @Autowired class 注入到您的 Runnable class 中。 new Runnable(){} 中的所有 @Autowired 对象已经无法从 spring.

访问

你可以参考这篇link来了解mkyong是如何使用ThreadPoolTask​​Executor的。请注意他命名为 class PrintTask implements Runnable 的部分。希望这有帮助 =)