[英]Spring Dependency Injection via @Configuration, @Bean and @Component
我一直在努力通過@Configuration
、 @Bean
和@Component
注釋完全理解依賴注入是如何工作的。
我的代碼如下。
1) Route.kt
/* Route.kt */
package com.example.service
import com.example.service.ports.AutoComplete
import com.example.service.ports.Validation
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType.APPLICATION_JSON
import org.springframework.web.reactive.function.server.router
@Configuration
@Suppress("unused")
class Routes(private val autoComplete: AutoComplete,
private val validation: Validation) {
@Bean
fun route() = router {
("/service-lookup" and accept(APPLICATION_JSON)).nest {
GET("/auto-complete/{service}", autoComplete::autoComplete)
GET("/validation/{service}", validation::validation)
}
}
}
2) ServiceImpl.kt
package com.example.service
import com.example.service.ports.AutoComplete
import com.example.service.ports.Validation
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono
@Component
@Suppress("unused")
class ServiceImpl: AutoComplete, Validation {
override fun autoComplete(request: ServerRequest): Mono<ServerResponse> {
TODO("not implemented autoComplete") //To change body of created functions use File | Settings | File Templates.
}
override fun validation(request: ServerRequest): Mono<ServerResponse> {
TODO("not implemented validation") //To change body of created functions use File | Settings | File Templates.
}
}
3) ports/AutoComplete.kt
package com.example.service.ports
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono
interface AutoComplete {
fun autoComplete(request: ServerRequest): Mono<ServerResponse>
}
4) ports/Validation.kt
package com.example.service.ports
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono
interface Validation {
fun validation(request: ServerRequest): Mono<ServerResponse>
}
我的問題是,如何將route
從創建豆Route.kt
知道, autoComplete
和validation
應使用ServiceImpl
類從ServiceImpl.kt
?
以下對 Spring 機制的描述為您簡化了示例:
在啟動時,Spring Boot 會掃描所有用@Configuration
、 @Component
等注釋的類的類路徑,並構建一個 bean 定義列表。 在您的示例中,它找到了Routes
和ServiceImpl
類。
在此之后,Spring 會掃描 bean 定義列表中每個類的所有方法以獲取進一步的@Bean
注釋,並將該方法(尤其是返回類型)添加到 bean 定義列表中。 在您的示例中,它找到了route
方法。
在第一次掃描之后,Spring 知道存在哪些 bean 類型以及哪個 bean 類實現了哪些接口。 Spring 知道創建 bean 實例需要哪些構造函數參數、 Inject
目標或方法參數。 有了這些信息,Spring 就會以正確的順序實例化 bean。 在您的示例中,Spring 知道Router
需要AutoComplete
和Validation
並且ServiceImpl
實現了這些接口。 因此它必須先實例化ServiceImpl
然后再實例化Router
。
如果不止一個 bean 實現了相同的接口,Spring 將拋出異常,您必須進一步限定該 bean。
我將嘗試澄清:
@Component - 它與 spring 自動配置和組件掃描緊密結合。 只要在@ComponentScanned 注解定義的組件掃描路徑中,所有標有 Component 的東西都會被拾取。 @Components 分為三種風格:
A) 存儲庫 - 用於持久化
B) 控制器,例如 RestController
C) 服務 - 沒有狀態的服務。 F.ex 一個門面。
該注解用於自動構建應用程序上下文,以及為綁定到上下文的 bean 定義構造型。
@Bean - @Bean 和 @Component 有相同的目標,但 @Bean 不是 @Component。 它們都構建了應用程序上下文,但它們以非常不同的方式進行構建。 而@Component 定義了類的構造型並告訴 spring 選擇它。 Bean 全權負責手動配置您正在創建的實例。 實現和配置是完全分離的,您可以更好地控制 Bean 的生成方式。
@Configuration與@Bean 結合使用。 @Bean 與 @Component 相比是一個方法級別的注解,因此通常的情況是一個類用 @Configuration 標記,然后還有一個用 @Bean 注釋的方法在后面。
在您的特定示例中,您創建了一個 @Bean 路由器。 路由器是基於注入到路由中的自動完成和驗證創建的。 Spring 能夠根據最佳匹配候選者確定要注入的內容。 由於您有兩個接口 AutoComplete 的單個實現 bean 實例,因此它會注入它。 在您的情況下, autoComplete 和驗證將指向同一個實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.