standalone springboot commandlinerunner application java spring command-line

java - springboot - Aplicación de consola de primavera configurada mediante anotaciones



spring command line arguments (6)

Eche un vistazo a Spring Reference, 3.2.2. Instanciando un contenedor .

Para utilizar Spring en la aplicación de consola, debe crear una instancia de ApplicationContext y obtener beans administrados por Spring desde ella.

Crear un contexto usando la configuración XML se describe en la Referencia. Para un enfoque completamente basado en anotaciones, puedes hacer algo como esto:

@Component // Main is a Spring-managed bean too, since it have @Autowired property public class Main { @Autowired SampleService sampleService; public static void main(String [] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext("package"); // Use annotated beans from the specified package Main main = ctx.getBean(Main.class); main.sampleService.getHelloWorld(); } }

Quiero crear la aplicación de la consola de primavera (ejecutándose desde la línea de comandos con maven, por ejemplo: mvn exec: java -Dexec.mainClass = "package.MainClass").

Es esta aplicación que quiero tener algún tipo de servicios y capas dao. Sé cómo hacerlo para una aplicación web, pero no he encontrado ninguna información sobre cómo hacerlo en el caso de una aplicación de consola (tal vez con Swing).

Estoy tratando de crear algo como:

public interface SampleService { public String getHelloWorld(); } @Service public class SampleServiceImpl implements SampleService { public String getHelloWorld() { return "HelloWorld from Service!"; } } public class Main { @Autowired SampleService sampleService; public static void main(String [] args) { Main main = new Main(); main.sampleService.getHelloWorld(); } }

¿Es posible? ¿Puedo encontrar en algún lugar un ejemplo de cómo hacerlo?


En cuanto a la respuesta de Chin Huang arriba ...

Tu ejemplo no funcionará, o al menos no funciona para mí localmente. Esto se debe a que está inicializando el objeto @Autowired con @Autowired , pero especifica AutowireCapableBeanFactory.AUTOWIRE_NO en las propiedades. En su lugar, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE en AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE o AutowireCapableBeanFactory.AUTOWIRE_BY_NAME .

Además, esto es extraño, entonces puedo estar haciendo algo mal. Pero parece que con AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE , tengo que tener un setProp() con @Autowired para que funcione. Entonces en vez de esto:

public class Main { @Autowired private SampleService sampleService; public static void main(String[] args) { Main main = new Main(); ApplicationContextLoader loader = new ApplicationContextLoader(); loader.load(main, "applicationContext.xml"); main.sampleService.getHelloWorld(); } }

Tengo que hacer esto:

public class Main { private SampleService sampleService; public static void main(String[] args) { Main main = new Main(); ApplicationContextLoader loader = new ApplicationContextLoader(); loader.load(main, "applicationContext.xml"); main.sampleService.getHelloWorld(); } @Autowired public void setSampleService(SampleService sampleService) { this.sampleService = sampleService; } }

Si tengo, como en el ejemplo original de Chin, datos privados con @Autowired , la DI falla. Estoy usando 3.1.1.RELEASE y creo que algunas de las cosas del auto-cableado han cambiado en 3.1.x, por lo que puede deberse a eso. Pero tengo curiosidad de por qué esto no funcionaría, ya que eso es consistente con versiones anteriores de Spring.


Esta fue mi solución para ejecutar una salida. Lo uso en un módulo que funciona como terreno común para todos los demás específicos: un sitio web y un API. Cuando especifico los argumentos correctos en el módulo correcto, ejecutaré la tarea correcta.

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration public class CLIApp { public static void main(String[] args) { ConfigurableApplicationContext ctx = new SpringApplicationBuilder(CLIApp.class) .web(false) .properties("spring.jmx.enabled=false") .run(args); final int exitCode = SpringApplication.exit(ctx); System.out.println("************************************"); System.out.println("* Console App sucessfully executed *"); System.out.println("************************************"); System.exit(exitCode); } }

Como puede ver, también desactivé el entorno web no utilizado y JMX. Me centraré en escanear el classpath del paquete de la clase y usar las habilidades de autoconfiguración de Spring Boot. Una vez que la aplicación termina de hacer lo que necesita, se cierra como una aplicación de consola.


Puedes hacerlo de esta manera:

  • Haz la inicialización en tu método principal
  • A continuación, puede utilizar el método de inicio como su controlador sudo

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; import com.org.service.YourService; @Component public class YourApp{ public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "ApplicationContext.xml"); YourApp p = context.getBean(App.class); p.start(args); } @Autowired YourService yourService; private void start(String[] args) { yourService.yourMethod(); } }


Tendría que resolver esto para un proyecto recientemente. Estaba construyendo una CLI para una utilidad que se ejecutaría desde un trabajo programado y una parte reutilizada del código de la aplicación web para el proyecto. Tuve un problema al inicializar todas las dependencias @Autowired, y realmente no las necesitaba todas, así que arranqué las dependencias específicas en la clase principal usando el método AnnotationConfigApplicationContext register (java.lang.Class ...) de la siguiente manera:

@Component public class SpringAppCLI { /** * Service to be autowired! */ @Autowired private SampleService sampleService; /** * */ public static void main(String[] args) throws Exception { final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // setup configuration applicationContext.register(SampleServiceConfig.class); applicationContext.register(SampleServiceRepository.class); applicationContext.register(JpaConfig.class); applicationContext.register(CommandLineConfig.class); applicationContext.register(SampleService.class); applicationContext.register(SpringAppCLI.class); // add CLI property source applicationContext.getEnvironment().getPropertySources() .addLast(new SimpleCommandLinePropertySource(args)); // setup all the dependencies (refresh) and make them run (start) applicationContext.refresh(); applicationContext.start(); try { SpringAppCLI springAppCLI = applicationContext.getBean(SpringAppCLI.class); springAppCLI.doWhatever(); } catch (Exception e) { //some handling } finally { applicationContext.close(); } } }

y aquí está la clase de configuración:

@Configuration @ComponentScan(basePackageClasses = SolrLoadCLI.class, includeFilters = @Filter(Controller.class), useDefaultFilters = false) class CommandLineConfig implements ApplicationContextAware { /** * */ private ApplicationContext applicationContext; /** * */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * * @return */ @Bean public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() { PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); Resource[] resourceArray = new Resource[2]; resourceArray[0] = new ClassPathResource("/SampleService.properties"); resourceArray[1] = new ClassPathResource("/Database.properties"); ppc.setLocations(resourceArray); return ppc; } }


The Spring Reference sugiere usar ClassPathXmlApplicationContext en el método main para crear el contexto de la aplicación, y luego llamar al método getBean para obtener una referencia inicial de un bean desde el contexto de la aplicación. Después de escribir este mismo código varias veces, terminas refaccionando el texto estándar en esta clase de utilidad:

/** * Bootstraps Spring-managed beans into an application. How to use: * <ul> * <li>Create application context XML configuration files and put them where * they can be loaded as class path resources. The configuration must include * the {@code <context:annotation-config/>} element to enable annotation-based * configuration, or the {@code <context:component-scan base-package="..."/>} * element to also detect bean definitions from annotated classes. * <li>Create a "main" class that will receive references to Spring-managed * beans. Add the {@code @Autowired} annotation to any properties you want to be * injected with beans from the application context. * <li>In your application {@code main} method, create an * {@link ApplicationContextLoader} instance, and call the {@link #load} method * with the "main" object and the configuration file locations as parameters. * </ul> */ public class ApplicationContextLoader { protected ConfigurableApplicationContext applicationContext; public ConfigurableApplicationContext getApplicationContext() { return applicationContext; } /** * Loads application context. Override this method to change how the * application context is loaded. * * @param configLocations * configuration file locations */ protected void loadApplicationContext(String... configLocations) { applicationContext = new ClassPathXmlApplicationContext( configLocations); applicationContext.registerShutdownHook(); } /** * Injects dependencies into the object. Override this method if you need * full control over how dependencies are injected. * * @param main * object to inject dependencies into */ protected void injectDependencies(Object main) { getApplicationContext().getBeanFactory().autowireBeanProperties( main, AutowireCapableBeanFactory.AUTOWIRE_NO, false); } /** * Loads application context, then injects dependencies into the object. * * @param main * object to inject dependencies into * @param configLocations * configuration file locations */ public void load(Object main, String... configLocations) { loadApplicationContext(configLocations); injectDependencies(main); } }

Llame al método de load en su método principal de aplicación. Tenga en cuenta que la clase Main no es un bean creado por Spring, y aún así puede inyectar una de sus propiedades con un bean desde el contexto de la aplicación.

public class Main { @Autowired private SampleService sampleService; public static void main(String[] args) { Main main = new Main(); new ApplicationContextLoader().load(main, "applicationContext.xml"); main.sampleService.getHelloWorld(); } }