我不能说 Kotlin(目前我对 kotlin 的了解相当有限),但在 Java 中,最后一个可用的 spring 版本(5.2.6.RELEASE)
我已经将它与您的示例的以下“kotlin to java”翻译一起使用:
public class RedirectProcessor {
private final AdProcessor adProcessor;
public RedirectProcessor(AdProcessor adProcessor) {
this.adProcessor = adProcessor;
}
public String run(int depth) {
if(depth < 3) {
return adProcessor.run(depth + 1);
}
else {
return "redirect";
}
}
}
public class FallbackProcessor {
private final AdProcessor adProcessor;
public FallbackProcessor(AdProcessor adProcessor) {
this.adProcessor = adProcessor;
}
public String run(int depth) {
if(depth < 3) {
return adProcessor.run(depth + 1);
}
else {
return "fallback";
}
}
}
public class AdProcessor {
private RedirectProcessor redirectProcessor;
private FallbackProcessor fallbackProcessor;
public AdProcessor(RedirectProcessor redirectProcessor, FallbackProcessor fallbackProcessor) {
this.redirectProcessor = redirectProcessor;
this.fallbackProcessor = fallbackProcessor;
}
public String run (int depth) {
return depth + redirectProcessor.run(depth) + fallbackProcessor.run(depth);
}
}
那么诀窍就是以不同的方式使用配置(但从 Java 配置规则的角度来看,这是完全“合法”的方式):
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public RedirectProcessor redirectProcessor (@Lazy AdProcessor adProcessor) {
return new RedirectProcessor(adProcessor);
}
@Bean
public FallbackProcessor fallbackProcessor (@Lazy AdProcessor adProcessor) {
return new FallbackProcessor(adProcessor);
}
@Bean
public AdProcessor adProcessor (RedirectProcessor redirectProcessor, FallbackProcessor fallbackProcessor) {
return new AdProcessor(redirectProcessor, fallbackProcessor);
}
@EventListener
public void onApplicationStarted(ApplicationStartedEvent evt) {
AdProcessor adProcessor = evt.getApplicationContext().getBean(AdProcessor.class);
String result = adProcessor.run(2);
System.out.println(result);
}
}
注意@Lazy 注释在参数上的用法,而不是在 bean 本身上。
监听器仅用于测试目的。运行应用程序打印23redirectfallback3redirectfallback
现在为什么它会起作用?
当 spring 看到这样的 @Lazy 注释参数时 - 它会从参数类创建一个运行时生成的代理(使用 CGLIB)。
此代理以包装 bean 的方式运行,并且仅在第一次“需要”时才会完全创建此 bean(请阅读,在这种情况下我们将调用此 bean 的方法)。
如果您使用@Component,则与以下声明相同:
@Component
public class FallbackProcessor {
private final AdProcessor adProcessor;
public FallbackProcessor(@Lazy AdProcessor adProcessor) {
this.adProcessor = adProcessor;
}
public String run(int depth) {
...
}
}
附带说明,我没有在最后一个示例中将@Autowired 放在FallbackProcessor 类的构造函数上,只是因为如果有一个构造函数,spring 会“识别”并使用它来注入所有依赖项。
SO 的following tutorial 和this somewhat old 线程也可能是相关的(值得一读)。