2011-01-24 65 views
31

我想創建Spring控制檯應用程序(從命令行運行maven,例如:mvn exec:java -Dexec.mainClass =「package.MainClass」)。使用註釋配置的Spring控制檯應用程序

這個應用程序我想要某種服務和dao層。我知道如何做一個Web應用程序,但我還沒有找到任何有關如何在控制檯應用程序的情況下(leter可能與Swing)的信息。

我想創造的東西,如:

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

這可能嗎? 我可以在某處找到一個如何去做的例子嗎?

回答

31

看看春季參考,3.2.2 Instantiating a container

爲了在控制檯應用程序中使用Spring,您需要創建一個ApplicationContext實例並從中獲取Spring管理的bean。

參考中描述了使用XML配置創建上下文。對於完全基於註解的方法,你可以做些事情是這樣的:

@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(); 
    } 
} 
+2

此外,如果像我一樣,你碰巧註釋你的配置: ctx = new AnnotationConfigApplicationContext(MyConfig.class); – 2012-03-30 01:19:27

+0

如何將命令行參數提供給應用程序上下文,以便上下文又可以將這些參數注入到bean中? – 2015-09-18 16:04:38

20

Spring參考建議在main方法使用ClassPathXmlApplicationContext創建應用程序上下文,然後調用getBean方法獲取的初始引用一個bean從應用程序上下文。寫相同的代碼幾次之後,你風重構樣板到這個工具類:

/** 
* 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); 
    } 
} 

調用load方法在應用程序中的主要方法。請注意,Main類不是Spring創建的bean,但您可以使用應用程序上下文中的bean注入其屬性之一。

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(); 
    } 
} 
3

關於上述欽黃的回答......

你的榜樣實際並不起作用,或者至少不是爲我工作地方。這是因爲您正在使用@Autowired初始化SampleService對象,但是您在屬性上指定了AutowireCapableBeanFactory.AUTOWIRE_NO。而應將其設置爲AutowireCapableBeanFactory.AUTOWIRE_BY_TYPEAutowireCapableBeanFactory.AUTOWIRE_BY_NAME

此外,這很奇怪,所以我可能做錯了什麼。但似乎與AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE,我必須有setProp()@Autowired它的工作。因此,而不是這樣的:

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

我必須這樣做:

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

如果我有,如齊秦的原始例如,@Autowired私人數據,該DI失敗。我使用的是3.1.1.RELEASE,我認爲3.1.x中的一些自動佈線的東西已經發生了變化,所以可能是由於這個原因。但我很好奇爲什麼這不起作用,因爲這符合Spring的早期版本。

2

你可以這樣來做:

  • 執行初始化在main方法
  • 然後可以使用start方法爲你的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(); 

    } 

} 
3

我最近想到了這個項目。我正在構建一個實用程序的CLI,該實用程序將從計劃作業運行並重用項目的部分Web應用程序代碼。我有一個引導所有@Autowired依賴的問題,而且我實際上並不需要它們,所以我使用AnnotationConfigApplicationContext寄存器(java.lang.Class ...)方法在主類中引導了特定的依賴關係,如下所示:

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

和這裏的配置類:

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

這是我的解決方案來運行一個出口。我在一個模塊中使用它作爲所有其他特定站點的共同點:一個網站和一個API。當我在正確的模塊上指定正確的參數時,它將運行正確的任務。

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

如您所見,我還禁用了未使用的Web環境和JMX。我將專注於從類的包中掃描類路徑,並使用Spring Boot的自動配置技能。 應用程序完成其所需的任務後,它將像控制檯應用程序一樣關閉。

相關問題