我正在尝试使用JFrame创建一个Spring启动应用程序。我可以在applicationContext中看到我的bean但它们没有得到自动装配。我无法找到这个问题的原因。有人可以帮我弄这个吗?
以下是代码:
JavauiApplication - 显示userManager和userNameRepository都是bean
@SpringBootApplication
public class JavauiApplication implements CommandLineRunner {
@Autowired
private ApplicationContext appContext;
public static void main(String[] args) {
new SpringApplicationBuilder(JavauiApplication.class).headless(false).run(args);
java.awt.EventQueue.invokeLater(() -> new InputNameForm().setVisible(true));
}
@Override
public void run(String... args) throws Exception {
String[] beans = appContext.getBeanDefinitionNames();
Arrays.sort(beans);
for (String bean : beans) {
System.out.println(bean);
}
}
}
InputNameForm.java - > userManager无效
@Component
public class InputNameForm extends javax.swing.JFrame {
/**
* Creates new form InputNameForm
*/
public InputNameForm() {
initComponents();
}
@Autowired
UserManager userManager;
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
userManager.setName(firstName.getText(), lastName.getText());
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(InputNameForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new InputNameForm().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTextField firstName;
private javax.swing.JLabel firstNameLabel;
private javax.swing.JTextField lastName;
private javax.swing.JLabel lastNameLabel;
private javax.swing.JButton submitButton;
// End of variables declaration//GEN-END:variables
}
UserManager.java - > userNameRepository将为空
@Component
public class UserManager {
@Autowired
UserNameRepository userNameRepository;
public void setName(String firstName, String lastName) {
userNameRepository.save(new UserName(firstName, lastName));
System.out.println(userNameRepository.findAllByFirstName(firstName));
}
}
答案 0 :(得分:1)
这是一个非常常见的问题,因为新手不了解IoC容器的工作原理。
BeanDefinitionReader
从XML,注释(@Component
,@Service
等),JavaConfig或Groovy脚本中读取有关bean的元数据。BeanPostProcessor
,负责阅读您正在撰写的所有这些Spring注释(@Autowired
等)。如果通过@Autowired
运算符创建具有new
依赖项的bean,会发生什么?没什么,因为它实际上并不是一个豆子。您创建的对象与IoC容器无关。如果你用@Component标记它,你可能已经在你的ApplicationContext
中有了bean,但是通过new
运算符创建的对象不会被Spring处理(注释不会被工作) )。
希望这有帮助。
PS:简化了生命周期。
答案 1 :(得分:0)
前几天我遇到了同样的问题。我所做的是,像netbeans一样的GUI构建器将使用new关键字自动创建组件。这意味着春天不会管理这些组件。代码通常像这样:
private void initComponents() {
jPanel1 = new javax.swing.JPanel(); //This component will not be managed by spring.
//...
}
您可以使用here提供的以下类来使其正常工作。
@Component
public class BeanProvider {
private static ApplicationContext applicationContext;
// Autowires the specified object in the spring context
public static void autowire(Object object) {
applicationContext.getAutowireCapableBeanFactory().autowireBean(object);
}
@Autowired
private void setApplicationContext(ApplicationContext applicationContext) {
BeanProvider.applicationContext = applicationContext;
}
}
顶级SwingApp类:
@SpringBootApplication
public class SwingApp implements CommandLineRunner {
public static void main(String[] args) {
new SpringApplicationBuilder(SwingApp.class)
.headless(false).bannerMode(Banner.Mode.OFF).run(args);
}
@Override
public void run(String... args) throws Exception {
SwingUtilities.invokeLater(() -> {
MainFrame frame = new MainFrame();
frame.setVisible(true);
});
}
}
MainFrame类:
public class MainFrame extends javax.swing.JFrame {
public MainFrame() {
initComponents();
}
private void initComponents() {
//Gui Builder generated code. Bean not managed by spring.
//Thus, autowired inside CustomPanel won't work if you rely on ComponentScan.
jPanel1 = new CustomJPanel();
//...
}
private CustomJPanel jPanel1;
}
要自动装配东西的面板类:
//@Component //not needed since it wont work with gui generated code.
public class CustomJPanel extends javax.swing.JPanel{
@Autowired
private SomeRepository someRepository
public CustomJPanel(){
BeanProvider.autowire(this); //use someRepository somewhere after this line.
}
}
答案 2 :(得分:0)
我在JavaFx项目中也遇到同样的问题。即使在上下文中显示了服务和组件注释的类,该类在UI控制器中也为空。下面的代码对我有用
@Component
public class FxmlLoaderWithContext {
private final ApplicationContext context;
@Autowired
public FxmlLoaderWithContext(ApplicationContext context) {
this.context = context;
FXMLLoader fxmlloader = new FXMLLoader();
fxmlloader.setControllerFactory(context::getBean); //this row ensure services and components to be autowired
}
}
答案 3 :(得分:0)
我认为它返回 null 是因为您使用命令 new
创建对象,例如 new InputNameForm()
。像这样创建对象时,该对象不是由 Spring 管理的。这就是为什么自动装配不起作用。
解决方案是将您的类注册为 bean。
您可以使用 here 中的类。
@Component
public class BeanProvider {
private static ApplicationContext applicationContext;
public static void autowire(Object object) {
applicationContext.getAutowireCapableBeanFactory().autowireBean(object);
}
@Autowired
private void setApplicationContext(ApplicationContext applicationContext) {
BeanProvider.applicationContext = applicationContext;
}
}
然后,在您的类 InputNameForm 构造函数中,调用:
class InputNameForm() {
BeanProvider.autowire(this);
...
}
就是这样。 Spring 会处理剩下的事情。