Spring Boot中Groovy DSL如何注入Autowired Bean?
在Groovy DSL中注入Spring管理的SNSService
场景说明
你正在运行一个依赖AWS的Spring Boot Java应用,使用Groovy实现DSL,需要在DSL的send()方法中调用Spring容器里的SNSService Bean。
期望的DSL用法
sendNotification{ topic 'topic' payload 'payload' send() }
现有代码
Groovy DSL类(src/main/groovy)
class SNSDsl{ String topic String payload void topic(String topic) { this.topic = topic } void payload(String payload) { this.payload = payload } void send(){ // 需要调用SNSService的sendNotification方法 } }
Spring服务类(src/main/java)
@Named public class SNSService { private final SnsOperations snsOperations; SNSService (SnsOperations snsOperations){ this.snsOperations = snsOperations; } public void sendNotification(final String payload, final String topic) { SnsNotification<String> notification = SnsNotification.builder(payload) .build(); snsOperations.sendNotification(topic, notification); } }
解决方案
Spring的依赖注入仅对容器内管理的Bean生效,这里提供两种可行方案:
方案一:将SNSDsl声明为Spring Bean,通过构造器注入SNSService
直接把SNSDsl纳入Spring容器管理,利用构造器注入SNSService,就能在send()方法中直接调用:
修改后的SNSDsl:
import org.springframework.stereotype.Component import javax.inject.Inject @Component class SNSDsl{ String topic String payload private final SNSService snsService // 构造器注入SNSService @Inject SNSDsl(SNSService snsService) { this.snsService = snsService } void topic(String topic) { this.topic = topic } void payload(String payload) { this.payload = payload } void send(){ snsService.sendNotification(payload, topic) } }
定义DSL入口方法(Spring Bean),用来启动DSL上下文:
import org.springframework.stereotype.Component import javax.inject.Inject @Component class SNSDslExecutor { private final SNSDsl snsDsl @Inject SNSDslExecutor(SNSDsl snsDsl) { this.snsDsl = snsDsl } void sendNotification(@DelegatesTo(SNSDsl) Closure closure) { closure.delegate = snsDsl closure.resolveStrategy = Closure.DELEGATE_FIRST closure.call() } }
之后在任意Spring管理的Bean中注入SNSDslExecutor,即可使用期望的DSL语法:
// 在某个Spring Bean中 @Inject private SNSDslExecutor dslExecutor // 使用DSL dslExecutor.sendNotification { topic 'my-topic' payload 'hello-world' send() }
方案二:手动传递SNSService到SNSDsl实例(不将SNSDsl纳入Spring容器)
如果不想让SNSDsl成为Spring Bean,可以在创建DSL实例时手动传入容器中的SNSService:
修改SNSDsl,添加带参数的构造器:
class SNSDsl{ String topic String payload private final SNSService snsService SNSDsl(SNSService snsService) { this.snsService = snsService } void topic(String topic) { this.topic = topic } void payload(String payload) { this.payload = payload } void send(){ snsService.sendNotification(payload, topic) } }
定义DSL入口,从Spring容器获取SNSService并传递给SNSDsl:
import org.springframework.stereotype.Component import javax.inject.Inject @Component class SNSDslExecutor { private final SNSService snsService @Inject SNSDslExecutor(SNSService snsService) { this.snsService = snsService } void sendNotification(@DelegatesTo(SNSDsl) Closure closure) { def snsDsl = new SNSDsl(snsService) closure.delegate = snsDsl closure.resolveStrategy = Closure.DELEGATE_FIRST closure.call() } }
使用方式和方案一完全一致,注入SNSDslExecutor即可调用DSL。
内容的提问来源于stack exchange,提问作者Pranesh Radhakrishnan
相关产品推荐
相关产品推荐

