standalone springboot commandlinerunner application java spring command-line

java - springboot - Tratando con argumentos de línea de comando y primavera



spring boot standalone java application (6)

Cuando estoy escribiendo una aplicación de línea de comandos de Spring que analiza argumentos de línea de comandos, ¿cómo los paso a Spring? ¿Me gustaría tener mi main () estructurado para que primero analice los argumentos de línea de comando y luego ingrese Spring? Aun así, ¿cómo pasaría el objeto que contiene los args analizados a Spring?


A partir de Spring 3.1 no es necesario ningún código personalizado sugerido en otras respuestas. Compruebe CommandLinePropertySource , proporciona una forma natural de insertar argumentos CL en su contexto.

Y si usted es un desarrollador afortunado de Spring Boot, podría simplificar su código un paso adelante aprovechando el hecho de que SpringApplication le ofrece lo siguiente:

De forma predeterminada, la clase realizará los siguientes pasos para iniciar su aplicación:

...

Registre CommandLinePropertySource para exponer los argumentos de la línea de comando como propiedades de Spring

Y si está interesado en el orden de resolución de propiedad de Spring Boot, consulte esta página .


Aquí hay un ejemplo para arrancar el resorte de correa para un método Principal, simplemente agarre los parámetros pasados ​​de manera normal y luego haga que la función que llame en su bean (en el caso deployer.execute ()) los tome como Cuerdas o mediante cualquier formato que considere adecuado .

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; }


Considera la siguiente clase:

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; } }

junto con:

/** * 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")); }


Dos posibilidades que puedo pensar

1) Establecer una referencia estática. (Una variable estática, aunque normalmente desaprobada, está bien en este caso, porque solo puede haber 1 invocación de línea de comando).

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

A continuación, puede hacer referencia a los argumentos de línea de comando en Spring a través de:

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

Alternativamente (si se opone completamente a las variables estáticas), puede:

2) Agregue programáticamente los argumentos al contexto de la aplicación:

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" }; }

El análisis de los argumentos de la línea de comando se deja como un ejercicio para el lector.


Eche un vistazo a mi biblioteca Spring-CLI, en http://github.com/sazzer/spring-cli , como una forma de hacerlo. Le proporciona una clase principal que carga automáticamente contextos de primavera y tiene la capacidad de usar Commons-CLI para analizar argumentos de línea de comando automáticamente e inyectarlos en sus beans.


También puede pasar una matriz de Objetos como un segundo parámetro para getBean que se usará como argumentos para el constructor o la fábrica.

public static void main(String[] args) { Mybean m = (Mybean)context.getBean("mybean", new Object[] {args}); }