Application console Spring configurée à l’aide d’annotations

Je veux créer une application console printanière (exécutée à partir de la ligne de commande avec maven, par exemple: mvn exec: java -Dexec.mainClass = “package.MainClass”).

Est-ce que cette application je veux avoir un certain type de services et de couches Dao. Je sais comment le faire pour une application Web, mais je n’ai trouvé aucune information sur la procédure à suivre dans le cas d’une application console (par exemple peut-être avec Swing).

J’essaie de créer quelque chose comme:

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

C’est possible? Puis-je trouver quelque part un exemple de la façon de le faire?

Jetez un coup d’œil à la référence de ressort, 3.2.2 Instanciation d’un conteneur .

Pour utiliser Spring dans une application console, vous devez créer une instance de ApplicationContext et en obtenir des beans gérés par Spring.

La création d’un contexte à l’aide de la configuration XML est décrite dans la référence. Pour une approche complètement basée sur les annotations, vous pouvez faire quelque chose comme ceci:

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

Spring Reference suggère d’utiliser ClassPathXmlApplicationContext dans la méthode main pour créer le contexte d’application, puis d’appeler la méthode getBean pour obtenir une référence initiale à un bean à partir du contexte d’application. Après avoir écrit ce même code plusieurs fois, vous finissez par refactoriser le passe-partout dans cette classe d’utilitaires:

 /** * Bootstraps Spring-managed beans into an application. How to use: * 
    *
  • Create application context XML configuration files and put them where * they can be loaded as class path resources. The configuration must include * the {@code } element to enable annotation-based * configuration, or the {@code } * element to also detect bean definitions from annotated classes. *
  • 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. *
  • 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. *
*/ 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(Ssortingng... 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, Ssortingng... configLocations) { loadApplicationContext(configLocations); injectDependencies(main); } }

Appelez la méthode de load dans la méthode principale de votre application. Notez que la classe Main n’est pas un bean créé par Spring, et pourtant vous pouvez injecter l’une de ses propriétés avec un bean depuis le contexte de l’application.

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

Je devrais trouver cela pour un projet récemment. Je construisais une interface de ligne de commande pour un utilitaire qui serait exécuté à partir d’un travail planifié et réutilisait une partie du code de l’application Web du projet. J’ai eu un problème de démarrage de toutes les dépendances @Autowired, et je n’en avais pas vraiment besoin, alors j’ai démarré les dépendances spécifiques de la classe principale en utilisant la méthode de registre AnnotationConfigApplicationContext (java.lang.Class …) comme suit:

 @Component public class SpringAppCLI { /** * Service to be autowired! */ @Autowired private SampleService sampleService; /** * */ public static void main(Ssortingng[] 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(); } } } 

et voici la classe de configuration:

 @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; } } 

En ce qui concerne la réponse de Chin Huang ci-dessus …

Votre exemple ne fonctionnera pas réellement ou du moins ne fonctionnera pas pour moi localement. En effet, vous initialisez l’object SampleService aide de @Autowired , mais vous spécifiez AutowireCapableBeanFactory.AUTOWIRE_NO sur les propriétés. Au lieu de cela, définissez-le sur AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE ou AutowireCapableBeanFactory.AUTOWIRE_BY_NAME .

Aussi, c’est étrange, alors je peux faire quelque chose de mal. Mais il semble qu’avec AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE , je dois avoir un setProp() avec @Autowired pour qu’il fonctionne. Donc au lieu de cela:

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

Je dois faire ceci:

 public class Main { private SampleService sampleService; public static void main(Ssortingng[] 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; } } 

Comme dans l’exemple original de Chin, si j’ai des données privées avec @Autowired , la DI échoue. J’utilise 3.1.1.RELEASE et je pense que certains des éléments de câblage automatique ont changé dans 3.1.x, donc cela peut être dû à cela. Mais je suis curieux de savoir pourquoi cela ne fonctionnerait pas, car cela correspond aux versions précédentes de Spring.

Vous pouvez le faire de cette façon:

  • Faire l’initialisation dans votre méthode principale
  • Vous pouvez ensuite utiliser la méthode de démarrage comme contrôleur 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(Ssortingng[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "ApplicationContext.xml"); YourApp p = context.getBean(App.class); p.start(args); } @Autowired YourService yourService; private void start(Ssortingng[] args) { yourService.yourMethod(); } } 

C’était ma solution pour exécuter une sortie. Je l’utilise dans un module qui fonctionne comme terrain d’entente avec tous les autres spécifiques: un site Web et un API. Lorsque je spécifie les bons arguments sur le bon module, la bonne tâche sera exécutée.

 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(Ssortingng[] 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); } } 

Comme vous le voyez, j’ai également désactivé l’environnement Web non utilisé et JMX. Je vais me concentrer sur l’parsing du classpath à partir du package de la classe et utiliser les compétences de configuration automatique de Spring Boot. Une fois que l’application a terminé, elle se ferme comme une application de console.