默认情况下,当您使用 @Singleton 等范围注释 bean 时,bean 类及其实现的所有接口和它扩展的超类都可以通过 @Inject 注入。
考虑上一节中有关定义 bean 的以下示例:
Java |
Groovy |
Kotlin |
@Singleton
public class V8Engine implements Engine { // (3)
@Override
public String start() {
return "Starting V8";
}
@Override
public int getCylinders() {
return 8;
}
}
|
@Singleton
class V8Engine implements Engine { // (3)
int cylinders = 8
@Override
String start() {
"Starting V8"
}
}
|
@Singleton
class V8Engine : Engine {
override var cylinders: Int = 8
override fun start(): String {
return "Starting V8"
}
}
|
在上述情况下,应用程序中的其他类可以选择注入接口 Engine 或具体实现 V8Engine。
如果这是不可取的,您可以使用 @Bean 注释的类型化成员来限制公开的类型。例如:
Java |
Groovy |
Kotlin |
@Singleton
@Bean(typed = Engine.class) // (1)
public class V8Engine implements Engine { // (2)
@Override
public String start() {
return "Starting V8";
}
@Override
public int getCylinders() {
return 8;
}
}
|
@Singleton
@Bean(typed = Engine) // (1)
class V8Engine implements Engine { // (2)
@Override
String start() { "Starting V8" }
@Override
int getCylinders() { 8 }
}
|
@Singleton
@Bean(typed = [Engine::class]) // (1)
class V8Engine : Engine { // (2)
override fun start(): String {
return "Starting V8"
}
override val cylinders: Int = 8
}
|
@Bean(typed=..) 用于只允许注入接口引擎而不是具体类型
该类必须实现typed定义的类或接口,否则会出现编译错误
以下测试演示了使用编程查找和 BeanContext API 进行类型化的行为:
Java |
Groovy |
Kotlin |
@MicronautTest
public class EngineSpec {
@Inject
BeanContext beanContext;
@Test
public void testEngine() {
assertThrows(NoSuchBeanException.class, () ->
beanContext.getBean(V8Engine.class) // (1)
);
final Engine engine = beanContext.getBean(Engine.class); // (2)
assertTrue(engine instanceof V8Engine);
}
}
|
class EngineSpec extends Specification {
@Shared @AutoCleanup
ApplicationContext beanContext = ApplicationContext.run()
void 'test engine'() {
when:'the class is looked up'
beanContext.getBean(V8Engine) // (1)
then:'a no such bean exception is thrown'
thrown(NoSuchBeanException)
and:'it is possible to lookup by the typed interface'
beanContext.getBean(Engine) instanceof V8Engine // (2)
}
}
|
@MicronautTest
class EngineSpec {
@Inject
lateinit var beanContext: BeanContext
@Test
fun testEngine() {
assertThrows(NoSuchBeanException::class.java) {
beanContext.getBean(V8Engine::class.java) // (1)
}
val engine = beanContext.getBean(Engine::class.java) // (2)
assertTrue(engine is V8Engine)
}
}
|
尝试查找 V8Engine 抛出 NoSuchBeanException
同时查找Engine接口成功
更多建议: