Pregunta

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

¿Fue útil?

Solución

Dos posibilidades que se me ocurren.

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

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

Luego puede hacer referencia a los argumentos de la línea de comandos en Spring a través de:

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

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

2) Agregue los argumentos al contexto de la aplicación mediante programació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.

Otros consejos

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

También puede pasar una matriz de objetos como 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});
}

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 inyectar argumentos CL en su contexto.

Y si eres un afortunado desarrollador de Spring Boot, podrías simplificar tu 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 reiniciar tu   aplicación:

     

...

     

Registre un CommandLinePropertySource para exponer los argumentos de la línea de comandos   como propiedades de primavera

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

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

}

Aquí hay un ejemplo para arrancar el resorte de la correa para un método principal, simplemente tome los parámetros pasados ??como de costumbre y luego haga que la función que llame a su bean (en el caso de deployer.execute ()) los tome como cadenas o mediante cualquier formato. te sientes 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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top