Lidar com argumentos de linha de comando e da mola
-
02-07-2019 - |
Pergunta
Quando estou escrevendo um aplicativo de linha de comando da Primavera que analisa os argumentos de linha de comando, como posso passá-las para Primavera? Será que eu quero ter o meu main () estruturado para que ele primeiro analisa os argumentos de linha de comando e, em seguida, inits Primavera? Mesmo assim, como seria passar o objeto segurando os argumentos analisado para Primavera?
Solução
Duas possibilidades que posso pensar.
1) Defina uma referência estática. (Uma variável estática, embora tipicamente desaprovada, é OK, neste caso, porque só pode haver uma linha de comando de chamada).
public class MyApp {
public static String[] ARGS;
public static void main(String[] args) {
ARGS = args;
// create context
}
}
Você pode fazer referência os argumentos da linha de comando na Primavera via:
<util:constant static-field="MyApp.ARGS"/>
Como alternativa (se você estiver completamente contrário de variáveis ??estáticas), você pode:
2) programaticamente adicionar os argumentos para o contexto do aplicativo:
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"
};
}
Analisando os argumentos de linha de comando é deixado como um exercício para o leitor.
Outras dicas
Tenha um olhar em minha biblioteca Spring-CLI - em http://github.com/sazzer/spring -cli - como uma maneira de fazer isso. Dá-lhe uma classe principal que carrega automaticamente contextos primavera e tem a capacidade de usar Commons-CLI para analisar argumentos de linha de comando automaticamente e injetando-os em seus feijões.
Você também pode passar uma matriz de objectos como um segundo parâmetro para getBean
que serão usados ??como argumentos para o construtor ou fábrica.
public static void main(String[] args) {
Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
A partir da Primavera 3.1, não há necessidade de qualquer código personalizado sugeriu em outras respostas. Verifique CommandLinePropertySource , ele fornece uma maneira natural para injetar argumentos CL em seu contexto.
E se você é um sortudo desenvolvedor Primavera de inicialização você pode simplificar o seu código um passo alavancar a frente o fato de que SpringApplication dá-lhe o seguinte:
Por padrão classe irá realizar os seguintes passos para inicializar o seu aplicativo:
...
Registrar um CommandLinePropertySource para expor os argumentos de linha de comando como propriedades da mola
E se você estiver interessado na ordem de resolução de propriedade Primavera Bota consulte desta página .
Considere a seguinte classe:
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;
}
}
juntamente com:
/**
* 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"));
}
Aqui está um exemplo de primavera cinta de inicialização para um método Main, simplesmente pegar os parâmetros passados ??como normal, então fazer a função que você chama em seu feijão (no caso deployer.execute ()) tomá-los como cordas ou através de qualquer formato você sente adequado.
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;
}