我想向我的项目中的一些子类注入 som 依赖项,但是它并没有像我想象的那样工作......我正在使用 Spring Boot 3.0.4 和 Java 17 用 Kotlin 1.8 编写。 0
我的课程如下所示:
@Service
sealed class Integration {
@Autowired lateinit var smsClient: SmsClient
@Autowired lateinit var emailClient: EmailClient
abstract val reference: UUID
abstract val integrationType: IntegrationType
abstract fun send(incomingMessage: String)
abstract fun getContactPoints(): List<String>
}
@Schema(description = "Integration of sms notifications.", allOf = [Integration::class])
class SmsIntegration(
override val reference: UUID = UUID.randomUUID(),
override val integrationType: IntegrationType = IntegrationType.SMS_INTEGRATION,
val countryCode: String,
val phoneNumbers: List<String>,
) : Integration() {
@PostConstruct
override fun send(incomingMessage: String) {
phoneNumbers.forEach { smsClient.postSms(SmsRequest(countryCode, it, incomingMessage)) }
}
override fun getContactPoints(): List<String> = this.phoneNumbers
fun copy(phoneNumbers: List<String>): SmsIntegration =
SmsIntegration(
reference = this.reference, countryCode = this.countryCode, phoneNumbers = phoneNumbers)
}
@Schema(description = "Integration of email notifications.", allOf = [Integration::class])
class EmailIntegration(
override val reference: UUID = UUID.randomUUID(),
override val integrationType: IntegrationType = IntegrationType.EMAIL_INTEGRATION,
val emails: List<String>,
val subject: String,
) : Integration() {
@PostConstruct
override fun send(incomingMessage: String) {
val emailAddresses: List<EmailAddress> = emails.map { EmailAddress(email = it) }
val email =
Email(
from = EmailAddress(email = "[email protected]"),
to = emailAddresses,
subject = subject,
body = incomingMessage)
emailClient.sendEmail(email)
}
override fun getContactPoints(): List<String> = this.emails
fun copy(emails: List<String>): EmailIntegration =
EmailIntegration(reference = this.reference, subject = this.subject, emails = emails)
}
@Schema(description = "Integration of slack notifications.", allOf = [Integration::class])
class SlackIntegration(
override val reference: UUID = UUID.randomUUID(),
override val integrationType: IntegrationType = IntegrationType.SLACK_INTEGRATION,
val channelIds: List<String>
) : Integration() {
fun copy(channelIds: List<String>): SlackIntegration =
SlackIntegration(reference = this.reference, channelIds = channelIds)
@PostConstruct
override fun send(incomingMessage: String) {
channelIds.forEach { SlackBot.sendMessage(channelId = it, message = incomingMessage) }
}
override fun getContactPoints(): List<String> = this.channelIds
}
如您所见,我的 Integration 课程中有两个自动连接的客户端,一个用于短信,一个用于电子邮件。我宁愿将它们放在单独的类中,但是我不想在创建这些类时在代码周围的构造函数中传递 emailClients 和 smsclients,因此我选择将它们放在 Integration 类中。但是,在 SmsIntegration 和 EmailIntegration 类中调用 send() 函数时,它们没有被初始化。
我觉得关于 spring boot 中的依赖注入,我的代码结构很糟糕。仅使用 slackBot 就很好,也很容易,因为它是一个单例,但是随着添加的依赖项,它变得一团糟..
感谢任何帮助重组或完成这项工作的人。
我不确定
@Schema
注释,
我假设它使您的课程成为组件
当你在做继承和Autowired时,一定要在setter上设置注释
@set:Autowired
,在这种情况下你甚至不需要用服务标记你的超类,
我认为在超类中获取实现是一个坏主意,正如评论中所提到的
@PostConstruct
并不是为了这个(我认为你想在这种情况下使用@EventListener
)
这是另一种方法:
// Integration.kt
interface Message
interface Integration {
fun send(message: Message)
fun supports(message: Message): Boolean
}
// SMSIntegration.kt
class SMS(val phoneNumber: String) : Message
@Service
class IntegrationSMS : Integration {
override fun send(message: Message) {
message as SMS
// send it
}
// implements send(SMS)
override fun supports(message: Message) = message is SMS
}
// SlackIntegration.kt
class SlackMessage : Message
@Service
class IntegrationSlack : Integration {
override fun send(message: Message) {
message as SlackMessage
}
// implements send(SlackMessage)
override fun supports(message: Message) = message is SlackMessage
}
// IntegrationManager.kt
@Service
class IntegrationManager(@Autowired val integrators: List<Integration> ){
@EventListener
fun sendMessage(message: Message){
for(integration in integrators)
if(integration.supports(message)
integration.send(message)
}
}
现在您可以在代码中的任何位置执行以下操作:
@Service
class SomewhereElse( val publisher: ApplicationEventPublisher){
fun doSomethingAndSendSMS(){
...
publisher.publish(SMS("1234"))
}
fun doSomethingAndSendSlackMessage(){
...
publisher.publish(SlackMessage())
}
}
如果你搁置
@EventListener
你可以直接调用IntegrationManager.sendMessage
这是SpringSecurity使用的实际方法(据我所知在servlet中)AuthenticationProvider
和AuthenticationManager
以及几个AuthenticationTokens