ThreadPoolTaskExecutor 中的@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
属性由 DI
和 NOT 启动由 new
。您的 Runnable 也由 new
关键字启动,这就是为什么我们需要从匿名 Runnable 对象中取出 myDirectoryReader
和 authThread
。
@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是如何使用ThreadPoolTaskExecutor的。请注意他命名为 class PrintTask implements Runnable
的部分。希望这有帮助 =)
我试图 运行 在 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
属性由 DI
和 NOT 启动由 new
。您的 Runnable 也由 new
关键字启动,这就是为什么我们需要从匿名 Runnable 对象中取出 myDirectoryReader
和 authThread
。
@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是如何使用ThreadPoolTaskExecutor的。请注意他命名为 class PrintTask implements Runnable
的部分。希望这有帮助 =)