Traitement des arguments de ligne de commande et de Spring
-
02-07-2019 - |
Question
Lorsque j'écris une application de ligne de commande Spring qui analyse les arguments de ligne de commande, comment puis-je les transmettre à Spring? Voudrais-je avoir ma structure main () structurée de manière à ce qu'elle analyse d'abord les arguments de la ligne de commande, puis dans Spring? Même dans ce cas, comment passerait-il l'objet contenant les arguments analysés à Spring?
La solution
Deux possibilités auxquelles je peux penser.
1) Définissez une référence statique. (Une variable statique, bien que généralement mal vue, est OK dans ce cas, car il ne peut y avoir qu'un seul appel de ligne de commande).
public class MyApp {
public static String[] ARGS;
public static void main(String[] args) {
ARGS = args;
// create context
}
}
Vous pouvez ensuite référencer les arguments de la ligne de commande dans Spring via:
<util:constant static-field="MyApp.ARGS"/>
Alternativement (si vous êtes complètement opposé aux variables statiques), vous pouvez:
2) Ajoutez par programme les arguments au contexte de l'application:
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"
};
}
L'analyse des arguments de la ligne de commande est laissée au lecteur sous forme d'exercice.
Autres conseils
Découvrez ma bibliothèque Spring-CLI à l'adresse http://github.com/sazzer/spring. -cli - comme moyen de le faire. Il vous donne une classe principale qui charge automatiquement les contextes de printemps et peut utiliser Commons-CLI pour analyser automatiquement les arguments de ligne de commande et les injecter dans vos beans.
Vous pouvez également transmettre un tableau Object en tant que second paramètre à getBean
, qui sera utilisé comme argument du constructeur ou de la fabrique.
public static void main(String[] args) {
Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
À partir de Spring 3.1, aucun code personnalisé suggéré dans d'autres réponses n'est nécessaire. Vérifiez CommandLinePropertySource . , il fournit un moyen naturel d’injecter des arguments CL dans votre contexte.
Et si vous êtes un développeur chanceux de Spring Boot, vous pouvez simplifier votre code un pas en avant, en exploitant le fait que SpringApplication vous donne les informations suivantes:
Par défaut, la classe effectuera les étapes suivantes pour amorcer votre application:
...
Enregistrez un CommandLinePropertySource pour exposer les arguments de ligne de commande en tant que propriétés Spring
Et si l'ordre de résolution des propriétés de Spring Boot vous intéresse, veuillez consulter cette page .
Considérez la classe suivante:
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;
}
}
avec:
/**
* 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"));
}
Voici un exemple pour amorcer le ressort d'une sangle pour une méthode Main. Il suffit de saisir les paramètres passés normalement puis de faire en sorte que la fonction que vous appelez sur votre haricot (dans le cas deployer.execute ()) vous vous sentez approprié.
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;
}