39

当我编写解析命令行参数的 Spring 命令行应用程序时,如何将它们传递给 Spring?我是否想让我的 main() 结构化,以便它首先解析命令行参数然后初始化 Spring?即便如此,它如何将保存已解析参数的对象传递给 Spring?

4

7 回答 7

40

我能想到的两种可能。

1)设置静态参考。(静态变量,虽然通常不受欢迎,但在这种情况下是可以的,因为只能有 1 个命令行调用)。

public class MyApp {
  public static String[] ARGS; 
  public static void main(String[] args) {
    ARGS = args;
      // create context
  }
}

然后,您可以通过以下方式引用 Spring 中的命令行参数:

<util:constant static-field="MyApp.ARGS"/>

或者(如果您完全反对静态变量),您可以:

2) 以编程方式将参数添加到应用程序上下文中:

 public class MyApp2 {
   public static void main(String[] args) {
     DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // Define a bean and register it
     BeanDefinition beanDefinition = BeanDefinitionBuilder.
       rootBeanDefinition(Arrays.class, "asList")
       .addConstructorArgValue(args).getBeanDefinition();
     beanFactory.registerBeanDefinition("args", beanDefinition);
     GenericApplicationContext cmdArgCxt = new GenericApplicationContext(beanFactory);
     // Must call refresh to initialize context 
     cmdArgCxt.refresh();

     // Create application context, passing command line context as parent
     ApplicationContext mainContext = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS, cmdArgCxt);

     // See if it's in the context
     System.out.println("Args: " + mainContext.getBean("args"));
   }

   private static String[] CONFIG_LOCATIONS = new String[] {
     "applicationContext.xml"
   };

 }

解析命令行参数留给读者作为练习。

于 2008-09-25T18:12:21.153 回答
7

看看我的 Spring-CLI 库 - 在http://github.com/sazzer/spring-cli - 作为这样做的一种方式。它为您提供了一个自动加载 spring 上下文的主类,并能够使用 Commons-CLI 自动解析命令行参数并将它们注入到您的 bean 中。

于 2010-01-15T12:41:38.673 回答
7

从 Spring 3.1 开始,其他答案中建议的任何自定义代码都不需要。检查CommandLinePropertySource,它提供了一种将 CL 参数注入上下文的自然方式。

如果您是一位幸运的 Spring Boot 开发人员,您可以利用SpringApplication为您提供以下事实的事实进一步简化您的代码:

默认情况下,类将执行以下步骤来引导您的应用程序:

...

注册一个 CommandLinePropertySource 以将命令行参数公开为 Spring 属性

如果您对 Spring Boot 属性解析顺序感兴趣,请查阅此页面

于 2017-01-27T07:46:44.180 回答
5

您还可以将 Object 数组作为第二个参数传递,该数组getBean将用作构造函数或工厂的参数。

public static void main(String[] args) {
   Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
于 2008-11-20T00:57:06.180 回答
3

考虑以下类:

public class ExternalBeanReferneceFactoryBean 
    extends AbstractFactoryBean
    implements BeanNameAware {

    private static Map<String, Object> instances = new HashMap<String, Object>();
    private String beanName;

    /**
     * @param instance the instance to set
     */
    public static void setInstance(String beanName, Object instance) {
        instances.put(beanName, instance);
    }

    @Override
    protected Object createInstance() 
        throws Exception {
        return instances.get(beanName);
    }

    @Override
    public Class<?> getObjectType() {
        return instances.get(beanName).getClass();
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

}

随着:

/**
 * Starts the job server.
 * @param args command line arguments
 */
public static void main(String[] args) {

    // parse the command line
    CommandLineParser parser = new GnuParser();
    CommandLine cmdLine = null;
    try {
        cmdLine = parser.parse(OPTIONS, args);
    } catch(ParseException pe) {
        System.err.println("Error parsing command line: "+pe.getMessage());
        new HelpFormatter().printHelp("command", OPTIONS);
        return;
    }

    // create root beanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // register bean definition for the command line
    ExternalBeanReferneceFactoryBean.setInstance("commandLine", cmdLine);
    beanFactory.registerBeanDefinition("commandLine", BeanDefinitionBuilder
        .rootBeanDefinition(ExternalBeanReferneceFactoryBean.class)
        .getBeanDefinition());

    // create application context
    GenericApplicationContext rootAppContext = new GenericApplicationContext(beanFactory);
    rootAppContext.refresh();

    // create the application context
    ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { 
        "/commandlineapp/applicationContext.xml"
    }, rootAppContext);

    System.out.println(appContext.getBean("commandLine"));

}
于 2009-07-28T16:29:27.653 回答
1

这是一个为 Main 方法引导 spring 的示例,只需像往常一样获取传递的参数,然后使您在 bean 上调用的函数(在这种情况下为 deployer.execute())将它们作为字符串或通过您认为合适的任何格式.

public static void main(String[] args) throws IOException, ConfigurationException {
    Deployer deployer = bootstrapSpring();

    deployer.execute();
}

private static Deployer bootstrapSpring()
{
    FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext("spring/deployerContext.xml");

    Deployer deployer = (Deployer)appContext.getBean("deployer");
    return deployer;
}
于 2008-09-25T10:39:58.680 回答
0

我不确定您到底要达到什么目标,也许您可​​以添加一些有关命令和参数的外观以及您期望从应用程序获得什么结果的详细信息。

我认为这不是您所需要的,但它可能会帮助其他读者:Spring 支持使用双连字符从命令行接收属性(例如java -jar app.jar --my.property="Property Value" ,查看此文档以获取更多信息: https ://docs.spring.io/spring -boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-command-line-args

于 2019-09-20T15:34:17.260 回答