处理命令行参数和Spring
时间:2020-03-06 14:42:37 来源:igfitidea点击:
当我编写一个解析命令行参数的Spring命令行应用程序时,如何将它们传递给Spring?我是否要对main()进行结构化,使其首先解析命令行args,然后解析其Spring?即使这样,它将如何将持有解析的args的对象传递给Spring?
解决方案
这是一个为Main方法引导皮带弹簧的示例,只需像往常一样简单地获取传递的参数,然后使我们在bean上调用的函数(在deployer.execute()的情况下)将它们作为String或者通过我们认为合适的任何格式。
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; }
我可以想到两种可能性。
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)以编程方式将args添加到应用程序上下文中:
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" }; }
解析命令行参数留给读者练习。
我们还可以将Object数组作为第二个参数传递给getBean,它将用作构造函数或者工厂的参数。
public static void main(String[] args) { Mybean m = (Mybean)context.getBean("mybean", new Object[] {args}); }
考虑以下类别:
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")); }
在http://github.com/sazzer/spring-cli上查看我的Spring-CLI库,这是实现此目的的一种方法。它为我们提供了一个自动加载spring上下文的主类,并具有使用Commons-CLI来自动解析命令行参数并将其注入到bean中的能力。