我尝试在Java GUI应用程序中按下按钮运行异步线程。
我的代码是:
配置类:
@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类:
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$4.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)
为什么会发生此异常?
如何修复此异常?
为什么我的组件没有自动装配?
谢谢。
答案 0 :(得分:2)
如果您的课程不是由上下文启动,则Bean将无法自动装配。换句话说,
如果您的类NewJFrame
由new
关键字手动启动,则spring框架将无法autowire
该类中的属性变量。
做这样的事情。
@Component("mainForm")
public class NewJFrame extends javax.swing.JFrame {
从配置java文件中删除bean方法mainForm
。然后重新设计NewJform,如下所示。我没有编译这个程序。对于任何编译错误,请原谅。
注意:关键是要确保@Autowired
内的所有DI
属性由new
启动, 由{{1}启用}}。您的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();
...
}
});
}
答案 1 :(得分:0)
基本上,你不应该使用
taskExecutor.execute(new Runnable(){
// do something here
});
首先,您必须了解什么是Managed Bean和Unmanaged Bean。当您使用Spring时,您的所有java类实例都将被实例化并且预先加载"你开始申请的那一刻。换句话说,所有类都将由spring容器实例化和管理。在实践中,您使用@Component(或@Bean,如果在@Configuration类中完成)和@Autowired注释。
当您使用" new" Runnable类的关键字,你正在做的是打破使用spring管理所有bean(或类)的规则。现在"new Runnable(){}"
不再由spring管理,但是你期望spring在你的Runnable类中注入所有@Autowired类。从{spring}开始,new Runnable(){}
中的所有@Autowired对象都已无法访问。
您可以参考此link来查看mkyong如何使用ThreadPoolTaskExecutor。请注意他命名为PrintTask implements Runnable
类的部分。希望这有助于=)