2011-01-24 36 views
31

Tôi muốn tạo ứng dụng bảng điều khiển lò xo (chạy từ dòng lệnh với maven chẳng hạn: mvn exec: java -Dexec.mainClass = "package.MainClass").Ứng dụng bảng điều khiển Spring được định cấu hình bằng cách sử dụng chú thích

Ứng dụng này tôi muốn có một số loại dịch vụ và lớp dao. Tôi biết làm thế nào để làm điều đó cho một ứng dụng web nhưng tôi đã không tìm thấy bất kỳ thông tin về làm thế nào để làm trong trường hợp của một ứng dụng giao diện điều khiển (leter có thể với Swing).

Tôi đang cố gắng để tạo ra một cái gì đó như:

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

Có thể? Tôi có thể tìm nơi nào đó làm ví dụ về cách thực hiện không?

Trả lời

31

Hãy xem Tài liệu tham khảo mùa xuân, 3.2.2 Instantiating a container.

Để sử dụng ứng dụng Mùa xuân trong bảng điều khiển, bạn cần tạo một phiên bản ApplicationContext và nhận các hạt được quản lý từ Spring.

Tạo ngữ cảnh bằng cách sử dụng cấu hình XML được mô tả trong Tham chiếu. Đối với cách tiếp cận hoàn toàn chú thích dựa trên, bạn có thể làm someting như thế này:

@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

Ngoài ra nếu như tôi bạn đã xảy ra chú thích cấu hình của bạn: ctx = new AnnotationConfigApplicationContext (MyConfig.class); –

+0

Làm thế nào bạn có thể cung cấp các đối số dòng lệnh cho ngữ cảnh ứng dụng để cho ngữ cảnh lần lượt có thể đưa các đối số này vào một bean? –

20

Các mùa xuân tham khảo gợi ý sử dụng ClassPathXmlApplicationContext trong phương pháp main để tạo ra bối cảnh ứng dụng, sau đó gọi phương thức getBean để có được một tài liệu tham khảo ban đầu để một bean từ ngữ cảnh ứng dụng. Sau khi viết cùng mã này một vài lần, bạn gió lên refactoring soạn sẵn vào lớp tiện ích này:

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

Gọi load phương pháp trong phương pháp chính ứng dụng của bạn. Lưu ý rằng lớp Main không phải là bean tạo Spring, và bạn có thể tiêm một trong các thuộc tính của nó với một bean từ ngữ cảnh ứng dụng.

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

Về câu trả lời Chin Huang trên ...

dụ của bạn sẽ không thực sự làm việc, hoặc ít nhất là không được làm việc cho tôi tại địa phương. Đó là vì bạn đang khởi tạo đối tượng SampleService bằng cách sử dụng @Autowired, nhưng bạn chỉ định AutowireCapableBeanFactory.AUTOWIRE_NO trên thuộc tính. Thay vào đó, hãy đặt nó thành AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE hoặc AutowireCapableBeanFactory.AUTOWIRE_BY_NAME.

Ngoài ra, điều này thật kỳ quặc, vì vậy tôi có thể đang làm điều gì đó sai. Nhưng có vẻ như với AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, tôi phải có setProp() với @Autowired để thiết bị hoạt động. Vì vậy, thay vì điều này:

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

tôi phải làm điều này:

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

Nếu tôi có, như trong ví dụ ban đầu của Chin, dữ liệu cá nhân với @Autowired, DI thất bại. Tôi đang sử dụng 3.1.1.RELEASE và tôi nghĩ rằng một số các công cụ tự động chuyển mạch đã thay đổi trong 3.1.x, do đó, nó có thể là do đó. Nhưng tôi tò mò là tại sao điều này sẽ không hiệu quả, vì nó phù hợp với các bản phát hành trước đó của Spring.

2

Bạn có thể làm theo cách này:

  • Làm khởi tạo trong phương pháp chính của bạn
  • Sau đó bạn có thể sử dụng phương pháp bắt đầu như điều khiển sudo bạn
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

Tôi muốn tìm ra điều này cho một dự án gần đây. Tôi đã xây dựng một CLI cho một tiện ích sẽ được chạy từ một công việc theo lịch trình và sử dụng lại một phần mã ứng dụng web cho dự án. Tôi đã có một vấn đề bootstrapping tất cả các phụ thuộc @Autowired, và tôi đã không thực sự cần tất cả, vì vậy tôi bootstrapped các phụ thuộc cụ thể trong lớp chính bằng cách sử dụng phương thức đăng ký AnnotationConfigApplicationContext (java.lang.Class ...) như sau:

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

và đây là lớp cấu hình:

@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

Đây là gọn gàng ... –

0

đây là giải pháp của tôi để chạy một lối ra. Tôi sử dụng nó trong một mô-đun hoạt động như nền tảng chung cho tất cả những người cụ thể khác: một trang web và một API. Khi tôi chỉ định đúng đối số trên mô-đun bên phải, nó sẽ chạy đúng tác vụ.

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

Như bạn thấy, tôi cũng vô hiệu hóa môi trường web chưa sử dụng và JMX. Tôi sẽ tập trung vào quét đường dẫn lớp từ gói của lớp và sử dụng các kỹ năng tự động cấu hình của Spring Boot. Sau khi ứng dụng kết thúc, thực hiện những gì nó cần nó đóng như một ứng dụng giao diện điều khiển.

Các vấn đề liên quan