如何将POJO传递给SpringBoot应用程序的运行方法?

时间:2018-11-23 20:10:09

标签: spring-boot

我有这个

  @Bean public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
       // use a lambda expression to define a CommandLineRunner
       return args -> { 
            ... work ... 
       }; 
  }

这样调用

  SpringApplication app = new SpringApplication(MyApp.class);
  app.run(args); // perform configuration magic and invoke the above lambda function

只要仅从CLI使用该应用程序,此方法就很好用。现在,该应用程序正在经历一些重构以支持新的运行时平台,现在我想这样做:

  app.run(complexOject); // pseudo-code, no such method in SpringApplication

即我需要将ComplexObject传递给应用程序,同时仍然保留所有神奇的自动配置。

这如何完成?首选代码更改量最少的解决方案。

2 个答案:

答案 0 :(得分:0)

使CommandLineRunner能够接收任意参数的重构步骤大致如下:

  1. ... work ...方法的内脏(commandLineRunner部分)移动到新bean类中的新方法,例如@Component public class GenericRunner { public void run(String ... args) ... }

  2. 这是最重要的步骤:完全删除原始的CommandLineRunner @Bean定义。执行配置后,这将导致应用程序的run()方法退出。

  3. app.run(args);调用替换为以下

    ConfigurableApplicationContext ctx = app.run(); // oh yeah
    GenericRunner runner = ctx.getBean(GenericRunner.class);
    runner.run(args);
    
  4. 重新运行所有测试,提交代码更改。

  5. 现在的实际重构很简单:随意修改runner.run(args)调用。这只是对GenericRunner POJO的直接调用,并且没有SpringBoot规则和限制。

答案 1 :(得分:-1)

SpringApplication类显然没有获取此输出流的方法,它是复杂且非常强大的Spring Boot应用程序加载过程的入口。

如果目标是存储应用程序的日志,请考虑使用日志记录配置而不是使用输出流。

否则,请描述需求,此输出流的目的是什么,我将尽力更新此答案。

更新:

SpringApplication启动一个应用程序上下文,该上下文用作应用程序中Spring bean的注册表。

因此,最“弹簧友好的解决方案”是将ComplexObject定义为一个Spring bean,以便将其注入可能需要它的其他bean中。 如果可以在应用程序启动期间创建此bean,那么它将非常有用。

示例:

class ComplexObject {...}

class ServiceThatMaintainsAReferenceOnObject {
   private ComplexObject complexObject;
   // all arg constructor
}


@Configuration 
class SpringConfiguration {

   @Bean
   public ComplexObject complexObject() {
      return new ComplexObject();
   }

   @Bean
   public ServiceThatMaintainsAReferenceOnObject service(ComplexObject complexObject) {
     return new ServiceThatMaintainsAReferenceOnObject(complexObject);
   }
}

现在,如果必须在Spring应用程序之外创建此复杂对象,则可能需要在创建应用程序上下文之后将其作为参数传递给某个bean方法。尽管这绝对不是Spring做事的方式,但这在问题中也可能是这种情况。

这里是一个例子:

 class ComplexObject {}
 class Service {
    void foo(ComplexObject complexObject);
 }


 @Configuration
 class MyConfiguration {
     @Bean
     public Service service() {
      return new Service();
     }
 } 

 // inside the main class of the application:

 SpringApplication app = ...
 ComplexObject complexObject = ... // get the object from somewhere
 ApplicationContext ctx = app.run(args); 
 // by this time, the context is started and ready
 Service service = ctx.getBean(Service.class);
 service.foo(complexObject); // call the method on bean managed by spring

总的来说,第二种方法通常不是spring应用程序的常规用例,尽管它的感觉就像您在问题中寻找类似的东西。

总的来说,我认为您应该简单地学习和理解Spring的工作原理,以及ApplicationContext到底能提供最佳解决方案(我很抱歉提到这一点,我这样说是因为从问题上讲看起来您尚未真正使用过Spring,也不太了解它的功能以及如何管理应用程序。