【问题标题】:Spring: Get Bean in main Method failsSpring:在 main 方法中获取 Bean 失败
【发布时间】:2016-06-25 13:38:20
【问题描述】:

我对 Java 和 Spring 框架都比较陌生。所以这是我正在构建的第一个 Spring 应用程序,我遇到了自动装配我的 Beans 的问题。

我的应用程序.java:

@SpringBootApplication
public class Application {

public static void main(String[] args) throws Exception {
    SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
    builder.headless(false);
    ConfigurableApplicationContext ctx = builder.run(args);
    AppRepository oAppRepo = ctx.getBean(AppRepository.class);
    // Check the SystemTray is supported
    if (!SystemTray.isSupported()) {
        System.out.println("SystemTray is not supported");
        return;
    }
    CustomTray oTray = ctx.getBean(CustomTray.class);
    }
}

我在 ressource 文件夹中的 config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    ">

<context:property-placeholder location="classpath:/application.properties"/>
<context:component-scan base-package="app"/>
<import resource="beans/*.xml" />
</beans>

我的豆子/tray.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="customTray" class="app.CustomTray">
    <property name="schedulerThread" value="app.SchedulerThread"></property>
    <property name="commandControlInterface" value="app.CommandControlInterface"></property>
</bean>
</beans>

我在启动时收到的错误消息:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [app.CustomTray] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:371)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968)
at app.Application.main(Application.java:46)

所以我不明白为什么没有合格的Bean,因为我在tray.xml中注册了bean。 CustomTray 类派生自 TrayIcon 类并创建一个 TrayIcon 没什么特别的,只是为了完成, 我的自定义托盘:

public class CustomTray extends TrayIcon {

private static final String IMAGE_PATH = "/images/icon.png";
private static final String TOOLTIP = "Test";

private PopupMenu popup;
private SystemTray tray;
@Autowired private AppRepository oAppRepo;

public CustomTray() {
    super(createImage(IMAGE_PATH, TOOLTIP), TOOLTIP);
    popup = new PopupMenu();
    tray = SystemTray.getSystemTray();
    try {
        this.setup();
    } catch (AWTException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@PostConstruct
private void setup() throws AWTException {

}

protected static Image createImage(String path, String description) {
    URL imageURL = CustomTray.class.getResource(path);
    if (imageURL == null) {
        System.err.println("Failed Creating Image. Resource not found: " + path);
        return null;
    } else {
        return new ImageIcon(imageURL, description).getImage();
    }
    }
}

我之前运行了应用程序,没有使用自动装配和 Beans,但现在我想重构并设置一个干净的 Spring 应用程序,我希望有人知道我做错了什么。

编辑: 好的,现在如果我使用 UUID 提到的注释导入 xml 文件,我会收到另一个错误消息。 bean customTray 有两个属性,SchedulerThread 属性也应该是一个 Singleton Bean。它在 beans/scheduler.xml 中声明,它本身也有一个属性,应该是一个 bean。像这样:

scheduler.xml

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="schedulerThread" class="app.SchedulerThread">
        <property name="processManager" value="app.ProcessManager"></property>
    </bean>
</beans>

错误:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'app.ProcessManager' for property 'processManager'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [app.ProcessManager] for property 'processManager': no matching editors or conversion strategy found

连接这些类和创建 Bean 的最佳方式是什么?正如我所说,我是 Spring 新手,我想我不了解它使用 bean 和自动装配的方式。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    在SpringBoot应用中,需要使用ImportResource注解来指定资源

    @ImportResource(locations = { "classpath:config.xml", "beans/tray.xml" })
    

    Spring Boot documentation - XML configuration

    您可以使用

    获取 bean 名称
    Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
    

    【讨论】:

      【解决方案2】:

      对我来说,解决方案是删除 XML-Config 文件并创建一个 AppConfig-File,现在我的 Application.java 看起来像这样:

          @SpringBootApplication
          public class Application {
              public static void main(String[] args) {
                  SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
                  builder.headless(false);
                  builder.run(args);
              }
          }
      

      AppConfig 是这样的:

          @Configuration
          public class AppConfig {
              @Autowired
              GridFsTemplate gridFSTemplate;
      
              @Autowired
              AppRepository appRepository;
      
              @Autowired
              UserRepository userRepository;
      
              @Bean
              ProcessManager processManager() {
                  return new ProcessManager();
              }
      
              @Bean
              SchedulerService schedulerService() {
                  SchedulerService schedulerService = new SchedulerService();
                  SchedulerService.setProcessManager(processManager());
                  SchedulerService.start();
                  return schedulerService;
              }
      
              @Bean
              CustomTray customTray() {
                  if (!SystemTray.isSupported()) {
                      System.out.println("SystemTray is not supported");
                      return null;
                  }
                  CustomTray customTray = new CustomTray();
                  customTray.setSchedulerService(schedulerService());
                  customTray.setAppRepository(this.appRepository);
                  try {
                      customTray.setup();
                  } catch (AWTException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
                  return customTray;
              }
      
              @Bean
              GridFSController gridFSController() {
                  GridFSController gridFSController = new GridFSController();
                  return gridFSController;
              }
          }
      

      现在我可以使用 Autowired 注释访问所有这些 Bean,我不需要那些 context.getBean() 东西。它大大减少了代码,我认为它是更清洁的解决方案。

      【讨论】:

        猜你喜欢
        • 2021-02-26
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 2012-05-14
        • 1970-01-01
        • 2011-05-25
        • 2014-12-04
        • 2017-03-09
        相关资源
        最近更新 更多