スプリングコンソールアプリケーションを作成したい(たとえば、コマンドラインからmavenを実行:mvn exec:Java -Dexec.mainClass = "package.MainClass")。
このアプリケーションは、ある種のサービスとdaoレイヤーが必要です。 Webアプリケーションでそれを行う方法は知っていますが、コンソールアプリケーションの場合(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();
}
}
出来ますか?どこでそれを行うかの例を見つけることができますか?
Spring Reference、 .2.2コンテナのインスタンス化 をご覧ください。
コンソールアプリケーションで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();
}
}
Spring Referenceでは、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);
}
}
アプリケーションのmainメソッドでload
メソッドを呼び出します。 Main
クラスはSpringで作成されたBeanではありませんが、そのプロパティの1つにアプリケーションコンテキストからの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();
}
}
最近、プロジェクトでこれを理解したいと思います。私は、スケジュールされたジョブから実行され、プロジェクトのWebアプリケーションコードの一部を再利用するユーティリティ用のCLIを構築していました。すべての@Autowired依存関係のブートストラップに問題があり、実際にはそれらすべてを必要としなかったため、次のようにAnnotationConfigApplicationContext register(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;
}
}
上記のChin Huangの答えについて...
あなたの例は実際には機能しないか、少なくとも私にとってはローカルでは機能しません。 _@Autowired
_を使用してSampleService
オブジェクトを初期化しているが、プロパティで_AutowireCapableBeanFactory.AUTOWIRE_NO
_を指定しているためです。代わりに、_AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE
_または_AutowireCapableBeanFactory.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;
}
}
_
Chinの元の例のように、_@Autowired
_のプライベートデータがある場合、DIは失敗します。 3.1.1.RELEASEを使用していますが、3.1.xでは自動配線機能の一部が変更されたため、それが原因である可能性があります。しかし、これが以前のリリースのSpringと一貫しているため、なぜこれが機能しないのか興味があります。
このようにすることができます:
- 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();
}
}
これが出口を実行するための私のソリューションでした。私は他のすべての特定のものに共通の基盤として機能するモジュールでそれを使用します:ウェブサイトと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の自動構成スキルを使用します。アプリケーションが必要な処理を完了すると、コンソールアプリのように閉じます。