2008-09-25 17 views
35

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?Tratando con los argumentos de línea de comandos y Spring

Respuesta

38

Dos posibilidades que se me ocurren.

1) Establezca 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 comandos en la primavera a través de:

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

alternativa (si usted es completamente opuesto a las variables estáticas), se puede:

2) añadir programación el args en el 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" 
}; 

} 

Analizando la línea de comando argum ents se deja como un ejercicio para el lector.

+4

1 para la referencia estática. 6 líneas de código son mejores que – Leonel

+0

20. Me gustó mucho esta solución y se encontraron de esta manera rizado para resolver el ejercicio: System.out.println ("Args:" + mainContext.getBean ("args")); \t \t Cadena [] arg1 = (Cadena []) ((Colección) mainContext.getBean ("args")). ToArray (new String [0]); \t \t Cadena o = arg1 [0]; \t \t System.out.println (o); – hephestos

1

Aquí hay un ejemplo del resorte de la correa de arranque para un método Principal, simplemente agarre los parámetros pasados ​​de manera normal y luego haga que la función que llama en su bean (en el caso deployer.execute()) los tome como cadenas o mediante cualquier formato que te parezca 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; 
} 
+0

Ah, yo debería haber mencionado que mi inicialización resorte debe venir después de la línea de comandos se ha analizado, ya que depende de los valores de la línea de comandos – lowellk

5

También puede pasar una matriz de Objetos como un segundo parámetro a 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}); 
} 
3

Considere la clase siguiente:

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

} 
6

Tenga una mirada en mi biblioteca Primavera-CLI - en http://github.com/sazzer/spring-cli - como una forma de hacer esto. 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.

4

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

Y si usted es una suerte desarrollador primavera de arranque se podría simplificar el código un paso adelante aprovechando el hecho de que SpringApplication que dicta la siguiente:

por clase por defecto llevará a cabo los siguientes pasos para arrancar su aplicación :

...

Registrar una CommandLinePropertySource para exponer los argumentos de línea de comandos como propiedades de primavera

Y si usted está interesado en el orden de arranque de la primavera resolución propiedad por favor consulte this page.

Cuestiones relacionadas