我有这个
@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
传递给应用程序,同时仍然保留所有神奇的自动配置。
这如何完成?首选代码更改量最少的解决方案。
答案 0 :(得分:0)
使CommandLineRunner
能够接收任意参数的重构步骤大致如下:
将... work ...
方法的内脏(commandLineRunner
部分)移动到新bean类中的新方法,例如@Component public class GenericRunner { public void run(String ... args) ... }
。
这是最重要的步骤:完全删除原始的CommandLineRunner @Bean
定义。执行配置后,这将导致应用程序的run()
方法退出。
将app.run(args);
调用替换为以下
ConfigurableApplicationContext ctx = app.run(); // oh yeah
GenericRunner runner = ctx.getBean(GenericRunner.class);
runner.run(args);
重新运行所有测试,提交代码更改。
现在的实际重构很简单:随意修改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,也不太了解它的功能以及如何管理应用程序。