[英]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.