Подтвердить что ты не робот

Консольное приложение Spring, настроенное с помощью аннотаций

Я хочу создать консольное приложение spring (выполняется из командной строки с maven, например: mvn exec: java -Dexec.mainclass= "package.MainClass" ).

Является ли это приложение, я хочу иметь какие-то службы и уровни dao. Я знаю, как это сделать для веб-приложения, но я не нашел никакой информации о том, как это сделать в случае консольного приложения (возможно, с 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();
 }
}

Возможно ли это? Могу ли я найти пример того, как это сделать?

4b9b3361

Ответ 1

Взгляните на Spring Reference, 3.2.2 Создание экземпляра контейнера.

Чтобы использовать Spring в консольном приложении, вам нужно создать экземпляр ApplicationContext и получить из него Spring -managed beans.

Создание контекста с использованием 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

Справочник Spring предлагает использовать ClassPathXmlApplicationContext в методе main для создания контекста приложения, а затем вызов 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 -created 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

Относительно ответа Чин Хуан выше...

Ваш пример на самом деле не работает или, по крайней мере, не работает для меня локально. Это потому, что вы инициализируете объект SampleService, используя @Autowired, но вы указываете 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.

Ответ 4

Я бы подумал об этом недавно. Я создавал 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;
    }
}

Ответ 5

Вы можете сделать это следующим образом:

  • Сделайте инициализацию в своем основном методе
  • Затем вы можете использовать метод 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();

    }

}

Ответ 6

Это было мое решение для запуска выхода. Я использую его в модуле, который работает как общий язык для всех других конкретных: веб-сайт и 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);
    }
}

Как вы видите, я также отключил неиспользуемую веб-среду и JMX. Я сосредоточусь на сканировании classpath из пакета класса и использовании навыков автоконфигурации Spring Boot. После того, как приложение закончит делать то, что ему нужно, оно закрывается, как консольное приложение.